@@ -414,11 +414,13 @@ func TestDirector_HandleRequest(t *testing.T) {
414414 initialTargetModelName string // Initial target model in the reqCtx.
415415 parser fwkrh.Parser
416416 wantErrCode string // Expected errcommon code string
417+ wantDroppedReason string // If non-empty, expected x-llm-d-request-dropped-reason header on the error
417418 wantReqCtx * handlers.RequestContext // Fields to check in the returned RequestContext
418419 targetModelName string // Expected model name after target model resolution
419420 admitRequestDenialError error // Expected denial error from admission plugin
420421 dataProducerPlugin * mockDataProducerPlugin
421422 screener * mockScreener
423+ emptyEndpoints bool // If true, the director locates no endpoint candidates.
422424 preRequestPlugins []* mockPreRequestPlugin
423425 requestHeaderPlugin * mockRequestHeaderPlugin
424426 wantMutatedBody map [string ]any
@@ -995,7 +997,21 @@ func TestDirector_HandleRequest(t *testing.T) {
995997 screener : & mockScreener {name : "eliminate-all" , screen : func ([]fwksched.Endpoint ) []fwksched.Endpoint {
996998 return nil
997999 }},
998- wantErrCode : errcommon .ServiceUnavailable ,
1000+ wantErrCode : errcommon .ServiceUnavailable ,
1001+ wantDroppedReason : string (errcommon .RequestDroppedReasonNoEndpoints ),
1002+ },
1003+ {
1004+ name : "no endpoint candidates located" ,
1005+ reqBodyMap : map [string ]any {
1006+ "model" : model ,
1007+ "prompt" : "critical prompt" ,
1008+ },
1009+ mockAdmissionController : & mockAdmissionController {admitErr : nil },
1010+ initialTargetModelName : model ,
1011+ inferenceObjectiveName : objectiveName ,
1012+ emptyEndpoints : true ,
1013+ wantErrCode : errcommon .ServiceUnavailable ,
1014+ wantDroppedReason : string (errcommon .RequestDroppedReasonNoEndpoints ),
9991015 },
10001016 {
10011017 name : "scheduler returns error" ,
@@ -1010,6 +1026,30 @@ func TestDirector_HandleRequest(t *testing.T) {
10101026 wantErrCode : errcommon .ResourceExhausted ,
10111027 inferenceObjectiveName : objectiveName ,
10121028 },
1029+ {
1030+ // The typed error inside a joined scheduler error, including its
1031+ // drop-reason header, must reach the caller instead of the
1032+ // untyped-error fallback.
1033+ name : "scheduler returns joined error with typed capacity rejection" ,
1034+ reqBodyMap : map [string ]any {
1035+ "model" : model ,
1036+ "prompt" : "prompt that causes scheduling drain" ,
1037+ },
1038+ mockAdmissionController : & mockAdmissionController {admitErr : nil },
1039+ schedulerMockSetup : func (m * mockScheduler ) {
1040+ m .scheduleErr = errors .Join (
1041+ errors .New ("failed to run scheduler profile 'default'" ),
1042+ fmt .Errorf ("profile %q: %w" , "default" , errcommon.Error {
1043+ Code : errcommon .ResourceExhausted ,
1044+ Msg : "no endpoints available for the given request" ,
1045+ Headers : map [string ]string {errcommon .RequestDroppedReasonHeaderKey : string (errcommon .RequestDroppedReasonSaturated )},
1046+ }),
1047+ )
1048+ },
1049+ wantErrCode : errcommon .ResourceExhausted ,
1050+ wantDroppedReason : string (errcommon .RequestDroppedReasonSaturated ),
1051+ inferenceObjectiveName : objectiveName ,
1052+ },
10131053 {
10141054 name : "scheduler returns nil result and nil error" ,
10151055 reqBodyMap : map [string ]any {
@@ -1090,6 +1130,9 @@ func TestDirector_HandleRequest(t *testing.T) {
10901130
10911131 endpointCandidates := NewCachedEndpointCandidates (context .Background (), NewDatastoreEndpointCandidates (ds ), time .Minute )
10921132 director := NewDirectorWithConfig (ds , mockSched , test .mockAdmissionController , endpointCandidates , config )
1133+ if test .emptyEndpoints {
1134+ director .endpointCandidates = & mockEndpointCandidates {}
1135+ }
10931136 if len (test .rewrites ) > 0 {
10941137 mockDs := & mockDatastore {
10951138 pods : ds .PodList (datastore .AllPodsPredicate ),
@@ -1140,6 +1183,9 @@ func TestDirector_HandleRequest(t *testing.T) {
11401183 var e errcommon.Error
11411184 if assert .ErrorAs (t , err , & e , "Error should be of type errcommon.Error" ) {
11421185 assert .Equal (t , test .wantErrCode , e .Code , "Error code mismatch" )
1186+ if test .wantDroppedReason != "" {
1187+ assert .Equal (t , test .wantDroppedReason , e .Headers [errcommon .RequestDroppedReasonHeaderKey ], "drop-reason header mismatch" )
1188+ }
11431189 }
11441190 return
11451191 }
0 commit comments