@@ -156,6 +156,11 @@ type processCallback struct {
156
156
// 4. If the replica is already in the queue and processing.
157
157
// - May be skipped if the replica is already in queue and no priority changes
158
158
// occur.
159
+ //
160
+ // Note that the callback may be invoked with (during bq.addInternal) or
161
+ // without holding the lock (bq.AddAsyncWithCallback, bq.SetMaxSize, defer in
162
+ // bq.addInternal) on baseQueue.mu. Important that the callback does not take
163
+ // too long to execute.
159
164
onEnqueueResult func (indexOnHeap int , err error )
160
165
161
166
// onProcessResult is called with the result of any process attempts. It is
@@ -165,6 +170,10 @@ type processCallback struct {
165
170
// re-processing.
166
171
// - May be skipped if the replica is removed with removeFromReplicaSetLocked
167
172
// or registered with a new replica id before processing begins.
173
+ //
174
+ // Note that the callback may be invoked with (during bq.MaybeAddCallback) or
175
+ // without holding the lock (bq.finishProcessingReplica) on baseQueue.mu.
176
+ // Important that the callback does not take too long to execute.
168
177
onProcessResult func (err error )
169
178
}
170
179
@@ -628,18 +637,37 @@ func (bq *baseQueue) SetDisabled(disabled bool) {
628
637
629
638
// SetMaxSize sets the max size of the queue.
630
639
func (bq * baseQueue ) SetMaxSize (maxSize int64 ) {
631
- bq .mu .Lock ()
632
- defer bq .mu .Unlock ()
633
- bq .mu .maxSize = maxSize
634
- // Drop replicas until no longer exceeding the max size. Note: We call
635
- // removeLocked to match the behavior of addInternal. In theory, only
636
- // removeFromQueueLocked should be triggered in removeLocked, since the item
637
- // is in the priority queue, it should not be processing or in the purgatory
638
- // queue. To be safe, however, we use removeLocked.
639
- for int64 (bq .mu .priorityQ .Len ()) > maxSize {
640
- pqLen := bq .mu .priorityQ .Len ()
641
- bq .full .Inc (1 )
642
- bq .removeLocked (bq .mu .priorityQ .sl [pqLen - 1 ])
640
+ var droppedItems []* replicaItem
641
+ func () {
642
+ bq .mu .Lock ()
643
+ defer bq .mu .Unlock ()
644
+ bq .mu .maxSize = maxSize
645
+ currentLen := int64 (bq .mu .priorityQ .Len ())
646
+ if currentLen > maxSize {
647
+ itemsToDrop := currentLen - maxSize
648
+ droppedItems = make ([]* replicaItem , 0 , itemsToDrop )
649
+
650
+ // Drop lower-priority replicas until no longer exceeding the max size.
651
+ // Note: We call removeLocked to match the behavior of addInternal. In
652
+ // theory, only removeFromQueueLocked should be triggered in removeLocked,
653
+ // since the item is in the priority queue, it should not be processing or
654
+ // in the purgatory queue. To be safe, however, we use removeLocked.
655
+ for int64 (bq .mu .priorityQ .Len ()) > maxSize {
656
+ lastIdx := bq .mu .priorityQ .Len () - 1
657
+ item := bq .mu .priorityQ .sl [lastIdx ]
658
+ droppedItems = append (droppedItems , item )
659
+ bq .removeLocked (item )
660
+ }
661
+ }
662
+ }()
663
+
664
+ // Notify callbacks outside the lock to avoid holding onto the lock for too
665
+ // long.
666
+ for _ , item := range droppedItems {
667
+ bq .updateMetricsOnDroppedDueToFullQueue ()
668
+ for _ , cb := range item .callbacks {
669
+ cb .onEnqueueResult (- 1 /*indexOnHeap*/ , errDroppedDueToFullQueueSize )
670
+ }
643
671
}
644
672
}
645
673
@@ -809,6 +837,14 @@ func (bq *baseQueue) updateMetricsOnEnqueueAdd() {
809
837
}
810
838
}
811
839
840
+ // updateMetricsOnDroppedDueToFullQueue updates the metrics when a replica is
841
+ // dropped due to a full queue size.
842
+ func (bq * baseQueue ) updateMetricsOnDroppedDueToFullQueue () {
843
+ if bq .full != nil {
844
+ bq .full .Inc (1 )
845
+ }
846
+ }
847
+
812
848
func (bq * baseQueue ) maybeAdd (ctx context.Context , repl replicaInQueue , now hlc.ClockTimestamp ) {
813
849
ctx = repl .AnnotateCtx (ctx )
814
850
ctx = bq .AnnotateCtx (ctx )
@@ -987,9 +1023,7 @@ func (bq *baseQueue) addInternal(
987
1023
// scan.
988
1024
if pqLen := bq .mu .priorityQ .Len (); int64 (pqLen ) > bq .mu .maxSize {
989
1025
replicaItemToDrop := bq .mu .priorityQ .sl [pqLen - 1 ]
990
- if bq .full != nil {
991
- bq .full .Inc (1 )
992
- }
1026
+ bq .updateMetricsOnDroppedDueToFullQueue ()
993
1027
log .Dev .VInfof (ctx , 1 , "dropping due to exceeding queue max size: priority=%0.3f, replica=%v" ,
994
1028
priority , replicaItemToDrop .replicaID )
995
1029
// TODO(wenyihu6): when we introduce base queue max size cluster setting,
0 commit comments