[refactor] Move ServerArgs ownership into the runtime context (stack 2/15) (#30064)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Cheng Wan
2026-07-04 02:20:34 -07:00
committed by GitHub
co-authored by Claude Fable 5
parent 6d662c9245
commit def20782cf
4 changed files with 103 additions and 51 deletions
@@ -33,6 +33,7 @@ from sglang.multimodal_gen.runtime.pipelines_core import Req
from sglang.srt import server_args as srt_server_args_module
from sglang.srt.observability import trace as srt_trace
from sglang.srt.observability.trace import TraceNullContext, TraceReqContext
from sglang.srt.runtime_context import reset_context
from sglang.srt.server_args import set_global_server_args_for_scheduler
try:
@@ -62,12 +63,18 @@ def _enable_minimal_otel() -> None:
@contextmanager
def _srt_trace_server_args():
prev_server_args = srt_server_args_module._global_server_args
try:
prev_server_args = srt_server_args_module.get_global_server_args()
except ValueError: # nothing published yet
prev_server_args = None
set_global_server_args_for_scheduler(SimpleNamespace(trace_modules="request"))
try:
yield
finally:
srt_server_args_module._global_server_args = prev_server_args
if prev_server_args is None:
reset_context()
else:
set_global_server_args_for_scheduler(prev_server_args)
def _traceparent_from(ctx) -> str | None:
+31 -13
View File
@@ -21,10 +21,12 @@ wrapper, not a cache. It gives call-sites one import and one naming scheme in
place of a dozen free functions, plus a test-only ``override()`` hook to force a
topology without monkeypatching the underlying getters.
``get_server_args()`` returns the process-wide ``ServerArgs`` (the config tier).
It is a read-through to ``server_args.get_global_server_args()`` — same object,
same pre-publish error — so new code can adopt the context accessor while the
legacy getter remains canonical.
``get_server_args()`` returns the process-wide ``ServerArgs`` (the config
tier). The context owns the storage: publishing goes through
``RuntimeContext.set_server_args`` (the legacy
``set_global_server_args_for_scheduler`` / ``get_global_server_args`` in
``server_args.py`` are thin shims over this slot), and the object is returned
by reference — the same live instance everywhere, never a copy.
"""
from __future__ import annotations
@@ -50,12 +52,6 @@ def _dp():
return dp_attention
def _sa():
from sglang.srt import server_args
return server_args
_PARALLEL_FIELDS = frozenset(
{
"world_size",
@@ -223,15 +219,29 @@ class RuntimeContext:
"""Container for the structured runtime accessors; exposes ``parallel`` and
``server_args``."""
__slots__ = ("parallel",)
__slots__ = ("parallel", "_server_args")
def __init__(self, parallel: ParallelContext):
self.parallel = parallel
self._server_args: ServerArgs | None = None
@property
def server_args(self) -> ServerArgs:
"""The process-wide ``ServerArgs``, read through the global getter."""
return _sa().get_global_server_args()
"""The process-wide ``ServerArgs`` (context-owned slot)."""
server_args = self._server_args
if server_args is None:
# Verbatim legacy message: tests and user scripts may match on it.
raise ValueError("Global server args is not set yet!")
return server_args
def set_server_args(self, server_args: ServerArgs) -> None:
"""Publish the process-wide ``ServerArgs`` into the context-owned slot.
Overwrite-allowed: a re-publish replaces the slot (test kits re-publish
per test; production ordering discipline lives at the call-sites, e.g.
the draft-worker guard in ``ModelRunner.__init__``).
"""
self._server_args = server_args
_PARALLEL = ParallelContext()
@@ -248,3 +258,11 @@ def get_parallel() -> ParallelContext:
def get_server_args() -> ServerArgs:
return _CONTEXT.server_args
def reset_context() -> None:
"""Clear the context-owned store (unit-test teardown).
Wrapper subsystems (``parallel``) hold no state and are unaffected.
"""
_CONTEXT._server_args = None
+9 -9
View File
@@ -7594,23 +7594,23 @@ class ServerArgs:
}
# NOTE: This is a global variable to hold the server args for scheduler.
_global_server_args: Optional[ServerArgs] = None
# NOTE: The process-wide ServerArgs is owned by the runtime context
# (sglang.srt.runtime_context). The two functions below are thin shims kept for
# the existing call-sites; they publish/read the same live object by reference.
# Imports are in-function so the two modules stay cycle-free at import time.
def set_global_server_args_for_scheduler(server_args: ServerArgs):
global _global_server_args
_global_server_args = server_args
from sglang.srt.runtime_context import get_context
get_context().set_server_args(server_args)
set_global_server_args_for_tokenizer = set_global_server_args_for_scheduler
def get_global_server_args() -> ServerArgs:
if _global_server_args is None:
raise ValueError("Global server args is not set yet!")
from sglang.srt.runtime_context import get_context
return _global_server_args
return get_context().server_args
def prepare_server_args(argv: List[str]) -> ServerArgs: