66import argparse
77import asyncio
88import sys
9+ import threading
910
1011from sglang_diffusion_routing import DiffusionRouter
12+ from sglang_diffusion_routing .launcher import config as _lcfg
1113
1214
1315def _run_router_server (
1416 args : argparse .Namespace ,
15- worker_urls : list [ str ] | None = None ,
17+ router : DiffusionRouter ,
1618 log_prefix : str = "[router]" ,
1719) -> None :
1820 try :
@@ -22,10 +24,7 @@ def _run_router_server(
2224 "uvicorn is required to run router. Install with: pip install uvicorn"
2325 ) from exc
2426
25- worker_urls = list (
26- worker_urls if worker_urls is not None else args .worker_urls or []
27- )
28- router = DiffusionRouter (args , verbose = args .verbose )
27+ worker_urls = list (args .worker_urls or [])
2928 refresh_tasks = []
3029 for url in worker_urls :
3130 normalized_url = router .normalize_worker_url (url )
@@ -97,13 +96,52 @@ def _add_router_args(parser: argparse.ArgumentParser) -> None:
9796 parser .add_argument (
9897 "--log-level" , type = str , default = "info" , help = "Uvicorn log level."
9998 )
99+ parser .add_argument (
100+ "--launcher-config" ,
101+ type = str ,
102+ default = None ,
103+ dest = "launcher_config" ,
104+ help = "YAML config for launching router managed workers (see examples/local_launcher.yaml)." ,
105+ )
100106
101107
102108def _handle_router (args : argparse .Namespace ) -> int :
103- _run_router_server (
104- args , worker_urls = list (args .worker_urls ), log_prefix = "[sglang-d-router]"
105- )
106- return 0
109+ log_prefix , backend , router = "[sglang-d-router]" , None , None
110+
111+ try :
112+ router = DiffusionRouter (args , verbose = args .verbose )
113+ if args .launcher_config is not None :
114+ launcher_cfg = _lcfg .load_launcher_config (args .launcher_config )
115+ wait_timeout = launcher_cfg .wait_timeout
116+ backend = _lcfg .create_backend (launcher_cfg )
117+ backend .launch ()
118+ threading .Thread (
119+ target = backend .wait_ready_and_register ,
120+ kwargs = dict (
121+ register_func = router .register_worker ,
122+ timeout = wait_timeout ,
123+ log_prefix = log_prefix ,
124+ ),
125+ daemon = True ,
126+ ).start ()
127+
128+ _run_router_server (args , router = router , log_prefix = log_prefix )
129+ return 0
130+ finally :
131+ # TODO (mengyang, shuwen, chenyang): refactor the exit logic of router and backend.
132+ if router is not None :
133+ try :
134+ asyncio .run (router .client .aclose ())
135+ except Exception as exc :
136+ print (
137+ f"{ log_prefix } warning: failed to close router client: { exc } " ,
138+ file = sys .stderr ,
139+ flush = True ,
140+ )
141+ if backend is not None :
142+ print (f"{ log_prefix } shutting down managed workers..." , flush = True )
143+ backend .shutdown ()
144+ print (f"{ log_prefix } all managed workers terminated." , flush = True )
107145
108146
109147def build_parser () -> argparse .ArgumentParser :
0 commit comments