@@ -367,6 +367,71 @@ func TestFlowController_EnqueueAndWait(t *testing.T) {
367367 assert .Equal (t , types .QueueOutcomeRejectedOther , outcome ,
368368 "outcome should be QueueOutcomeRejectedOther on shutdown" )
369369 })
370+ t .Run ("OnControllerShutdownDuringFinalization" , func (t * testing.T ) {
371+ t .Parallel ()
372+ ctx , cancel := context .WithCancel (t .Context ())
373+ h := newUnitHarness (ctx , t , & Config {}, nil , nil )
374+ item := internal .NewItem (newTestRequest (defaultFlowKey ), 0 , time .Now ())
375+
376+ result := make (chan struct {
377+ outcome types.QueueOutcome
378+ err error
379+ }, 1 )
380+ go func () {
381+ outcome , err := h .fc .awaitFinalization (context .Background (), item )
382+ result <- struct {
383+ outcome types.QueueOutcome
384+ err error
385+ }{outcome : outcome , err : err }
386+ }()
387+
388+ cancel ()
389+ select {
390+ case r := <- result :
391+ require .Error (t , r .err , "awaitFinalization must fail when controller shuts down" )
392+ assert .ErrorIs (t , r .err , types .ErrFlowControllerNotRunning ,
393+ "error should wrap ErrFlowControllerNotRunning" )
394+ assert .Equal (t , types .QueueOutcomeRejectedOther , r .outcome ,
395+ "outcome should be QueueOutcomeRejectedOther on shutdown" )
396+ case <- time .After (time .Second ):
397+ t .Fatal ("awaitFinalization did not return after controller shutdown" )
398+ }
399+ })
400+ t .Run ("OnControllerShutdownTakesPrecedenceOverRequestCancellation" , func (t * testing.T ) {
401+ t .Parallel ()
402+ ctx , cancel := context .WithCancel (t .Context ())
403+ h := newUnitHarness (ctx , t , & Config {}, nil , nil )
404+ reqCtx , reqCancel := context .WithCancel (context .Background ())
405+ item := internal .NewItem (newTestRequest (defaultFlowKey ), 0 , time .Now ())
406+
407+ reqCancel ()
408+ cancel ()
409+
410+ outcome , err := h .fc .awaitFinalization (reqCtx , item )
411+ require .Error (t , err , "awaitFinalization must fail when controller shuts down" )
412+ assert .ErrorIs (t , err , types .ErrFlowControllerNotRunning ,
413+ "controller shutdown should take precedence over request cancellation" )
414+ assert .Equal (t , types .QueueOutcomeRejectedOther , outcome ,
415+ "shutdown should return the rejected outcome" )
416+ })
417+ t .Run ("OnControllerShutdownPreservesQueuedOutcome" , func (t * testing.T ) {
418+ t .Parallel ()
419+ ctx , cancel := context .WithCancel (t .Context ())
420+ h := newUnitHarness (ctx , t , & Config {}, nil , nil )
421+ item := internal .NewItem (newTestRequest (defaultFlowKey ), 0 , time .Now ())
422+ item .SetHandle (& fwkfcmocks.MockQueueItemHandle {})
423+
424+ cancel ()
425+
426+ outcome , err := h .fc .awaitFinalization (context .Background (), item )
427+ require .Error (t , err , "awaitFinalization must fail when controller shuts down" )
428+ assert .ErrorIs (t , err , types .ErrEvicted ,
429+ "a queued item should be evicted, not rejected, during shutdown" )
430+ assert .ErrorIs (t , err , types .ErrFlowControllerNotRunning ,
431+ "queued shutdown should preserve the shutdown cause" )
432+ assert .Equal (t , types .QueueOutcomeEvictedOther , outcome ,
433+ "a queued item should return the evicted outcome" )
434+ })
370435
371436 t .Run ("OnRegistryConnectionError" , func (t * testing.T ) {
372437 t .Parallel ()
0 commit comments