@@ -343,6 +343,122 @@ func TestWorkqueueDeduplication_DifferentNodes(t *testing.T) {
343343 queueImpl .queue .Done (item2 )
344344}
345345
346+ func TestPriorityQueue_GroupedFloodPrioritizesUnrepresentedNodes (t * testing.T ) {
347+ mgr := NewEventQueueManager ()
348+ defer mgr .Shutdown ()
349+
350+ ctx := context .Background ()
351+ mockDB := & mockDataStore {}
352+ mockHealthEventStore := & MockHealthEventStore {}
353+
354+ node1Event1 := datastore.Event {
355+ "_id" : "507f1f77bcf86cd799439011" ,
356+ "nodeName" : "node-1" ,
357+ }
358+ node1Event2 := datastore.Event {
359+ "_id" : "507f1f77bcf86cd799439012" ,
360+ "nodeName" : "node-1" ,
361+ }
362+ node2Event1 := datastore.Event {
363+ "_id" : "507f1f77bcf86cd799439013" ,
364+ "nodeName" : "node-2" ,
365+ }
366+
367+ require .NoError (t , mgr .EnqueueEventGeneric (ctx , "node-1" , node1Event1 , mockDB , mockHealthEventStore , node1Event1 ["_id" ]))
368+ require .NoError (t , mgr .EnqueueEventGeneric (ctx , "node-1" , node1Event2 , mockDB , mockHealthEventStore , node1Event2 ["_id" ]))
369+ require .NoError (t , mgr .EnqueueEventGeneric (ctx , "node-2" , node2Event1 , mockDB , mockHealthEventStore , node2Event1 ["_id" ]))
370+
371+ queueImpl := mgr .(* eventQueueManager )
372+
373+ item1 , shutdown := queueImpl .queue .Get ()
374+ require .False (t , shutdown )
375+ assert .Equal (t , "507f1f77bcf86cd799439011" , item1 .EventID )
376+
377+ item2 , shutdown := queueImpl .queue .Get ()
378+ require .False (t , shutdown )
379+ assert .Equal (t , "507f1f77bcf86cd799439013" , item2 .EventID , "unrepresented node gets the high-priority lane" )
380+
381+ item3 , shutdown := queueImpl .queue .Get ()
382+ require .False (t , shutdown )
383+ assert .Equal (t , "507f1f77bcf86cd799439012" , item3 .EventID , "duplicate work for represented node remains low priority" )
384+
385+ queueImpl .queue .Done (item1 )
386+ queueImpl .queue .Done (item2 )
387+ queueImpl .queue .Done (item3 )
388+ }
389+
390+ func TestPriorityQueue_DrainingNodesStayLowPriorityUntilCleared (t * testing.T ) {
391+ mgr := NewEventQueueManager ()
392+ defer mgr .Shutdown ()
393+
394+ ctx := context .Background ()
395+ mockDB := & mockDataStore {}
396+ mockHealthEventStore := & MockHealthEventStore {}
397+
398+ queueImpl := mgr .(* eventQueueManager )
399+ queueImpl .MarkNodeDraining ("node-1" )
400+
401+ node1DrainingEvent := datastore.Event {
402+ "_id" : "507f1f77bcf86cd799439021" ,
403+ "nodeName" : "node-1" ,
404+ }
405+ node2Event := datastore.Event {
406+ "_id" : "507f1f77bcf86cd799439022" ,
407+ "nodeName" : "node-2" ,
408+ }
409+ node1AfterClearEvent := datastore.Event {
410+ "_id" : "507f1f77bcf86cd799439023" ,
411+ "nodeName" : "node-1" ,
412+ }
413+
414+ require .NoError (t , mgr .EnqueueEventGeneric (ctx , "node-1" , node1DrainingEvent , mockDB , mockHealthEventStore , node1DrainingEvent ["_id" ]))
415+ require .NoError (t , mgr .EnqueueEventGeneric (ctx , "node-2" , node2Event , mockDB , mockHealthEventStore , node2Event ["_id" ]))
416+
417+ item1 , shutdown := queueImpl .queue .Get ()
418+ require .False (t , shutdown )
419+ assert .Equal (t , "507f1f77bcf86cd799439022" , item1 .EventID , "not-yet-draining node should run before draining duplicate work" )
420+
421+ queueImpl .ClearNodeDraining ("node-1" )
422+ require .NoError (t , mgr .EnqueueEventGeneric (ctx , "node-1" , node1AfterClearEvent , mockDB , mockHealthEventStore , node1AfterClearEvent ["_id" ]))
423+
424+ item2 , shutdown := queueImpl .queue .Get ()
425+ require .False (t , shutdown )
426+ assert .Equal (t , "507f1f77bcf86cd799439023" , item2 .EventID , "cleared node can receive high priority again" )
427+
428+ item3 , shutdown := queueImpl .queue .Get ()
429+ require .False (t , shutdown )
430+ assert .Equal (t , "507f1f77bcf86cd799439021" , item3 .EventID )
431+
432+ queueImpl .queue .Done (item1 )
433+ queueImpl .queue .Done (item2 )
434+ queueImpl .queue .Done (item3 )
435+ }
436+
437+ func TestPriorityQueue_NonComparableDocumentID_DoesNotPanic (t * testing.T ) {
438+ state := newNodePriorityState ()
439+ queueImpl := newNodeEventPriorityQueue (state )
440+ item := NodeEvent {
441+ NodeName : "node-1" ,
442+ EventID : "event-1" ,
443+ DocumentID : map [string ]string {"id" : "non-comparable" },
444+ }
445+
446+ require .NotPanics (t , func () {
447+ queueImpl .Push (item )
448+ entry := state .nodes [item .NodeName ]
449+ require .Equal (t , nodePriorityStateRepresented , entry .kind )
450+ require .Equal (t , representativeKey (item ), entry .representativeKey )
451+
452+ got := queueImpl .Pop ()
453+ assert .Equal (t , item .NodeName , got .NodeName )
454+ assert .Equal (t , item .EventID , got .EventID )
455+
456+ state .releaseRepresentative (got )
457+ _ , represented := state .nodes [item .NodeName ]
458+ assert .False (t , represented )
459+ })
460+ }
461+
346462// Mock DataStore for testing
347463type mockDataStore struct {}
348464
0 commit comments