1414from dstack ._internal .core .errors import GatewayError , SSHError
1515from dstack ._internal .core .models .backends .base import BackendType
1616from dstack ._internal .core .models .common import NetworkMode , RegistryAuth
17- from dstack ._internal .core .models .configurations import DevEnvironmentConfiguration
17+ from dstack ._internal .core .models .configurations import (
18+ DevEnvironmentConfiguration ,
19+ ServiceConfiguration ,
20+ )
1821from dstack ._internal .core .models .files import FileArchiveMapping
1922from dstack ._internal .core .models .instances import InstanceStatus , SSHConnectionParams
2023from dstack ._internal .core .models .metrics import Metric
@@ -991,6 +994,22 @@ async def _register_service_replica(
991994 if context .run_model .gateway_id is None :
992995 return None
993996
997+ job_spec = JobSpec .__response__ .parse_raw (context .job_model .job_spec_data )
998+
999+ # For router-based services (e.g. PD disaggregation), only router replicas should be
1000+ # registered with the gateway. Worker replicas are discovered by the router-worker
1001+ # sync pipeline and should not be routed to directly by the gateway.
1002+ config = context .run .run_spec .configuration
1003+ assert isinstance (config , ServiceConfiguration )
1004+ router_group = next ((g for g in config .replica_groups if g .router is not None ), None )
1005+ is_router_replica = router_group is not None and job_spec .replica_group == router_group .name
1006+ if router_group is not None and not is_router_replica :
1007+ logger .debug (
1008+ "%s: skipping gateway replica registration (non-router replica)" ,
1009+ fmt (context .job_model ),
1010+ )
1011+ return None
1012+
9941013 async with get_session_ctx () as session :
9951014 gateway_model , conn = await get_or_add_gateway_connection (
9961015 session , context .run_model .gateway_id
@@ -1011,7 +1030,7 @@ async def _register_service_replica(
10111030 async with conn .client () as gateway_client :
10121031 await gateway_client .register_replica (
10131032 run = context .run ,
1014- job_spec = JobSpec . __response__ . parse_raw ( context . job_model . job_spec_data ) ,
1033+ job_spec = job_spec ,
10151034 job_submission = job_submission ,
10161035 instance_project_ssh_private_key = instance_project_ssh_private_key ,
10171036 ssh_head_proxy = ssh_head_proxy ,
0 commit comments