@@ -406,6 +406,12 @@ func (r *Reflector) ListAndWatchWithContext(ctx context.Context) error {
406
406
useWatchList := ptr .Deref (r .UseWatchList , false )
407
407
fallbackToList := ! useWatchList
408
408
409
+ defer func () {
410
+ if w != nil {
411
+ w .Stop ()
412
+ }
413
+ }()
414
+
409
415
if useWatchList {
410
416
w , err = r .watchList (ctx )
411
417
if w == nil && err == nil {
@@ -476,22 +482,28 @@ func (r *Reflector) watchWithResync(ctx context.Context, w watch.Interface) erro
476
482
return r .watch (ctx , w , resyncerrc )
477
483
}
478
484
479
- // watch simply starts a watch request with the server.
485
+ // watch starts a watch request with the server, consumes watch events, and
486
+ // restarts the watch until an exit scenario is reached.
487
+ //
488
+ // If a watch is provided, it will be used, otherwise another will be started.
489
+ // If the watcher has started, it will always be stopped before returning.
480
490
func (r * Reflector ) watch (ctx context.Context , w watch.Interface , resyncerrc chan error ) error {
481
491
stopCh := ctx .Done ()
482
492
logger := klog .FromContext (ctx )
483
493
var err error
484
494
retry := NewRetryWithDeadline (r .MaxInternalErrorRetryDuration , time .Minute , apierrors .IsInternalError , r .clock )
495
+ defer func () {
496
+ if w != nil {
497
+ w .Stop ()
498
+ }
499
+ }()
485
500
486
501
for {
487
502
// give the stopCh a chance to stop the loop, even in case of continue statements further down on errors
488
503
select {
489
504
case <- stopCh :
490
505
// we can only end up here when the stopCh
491
506
// was closed after a successful watchlist or list request
492
- if w != nil {
493
- w .Stop ()
494
- }
495
507
return nil
496
508
default :
497
509
}
@@ -529,8 +541,8 @@ func (r *Reflector) watch(ctx context.Context, w watch.Interface, resyncerrc cha
529
541
530
542
err = handleWatch (ctx , start , w , r .store , r .expectedType , r .expectedGVK , r .name , r .typeDescription , r .setLastSyncResourceVersion ,
531
543
r .clock , resyncerrc )
532
- // Ensure that watch will not be reused across iterations .
533
- w . Stop ()
544
+ // handleWatch always stops the watcher. So we don't need to here .
545
+ // Just set it to nil to trigger a retry on the next loop.
534
546
w = nil
535
547
retry .After (err )
536
548
if err != nil {
@@ -863,6 +875,12 @@ func handleAnyWatch(
863
875
logger := klog .FromContext (ctx )
864
876
initialEventsEndBookmarkWarningTicker := newInitialEventsEndBookmarkTicker (logger , name , clock , start , exitOnWatchListBookmarkReceived )
865
877
defer initialEventsEndBookmarkWarningTicker .Stop ()
878
+ stopWatcher := true
879
+ defer func () {
880
+ if stopWatcher {
881
+ w .Stop ()
882
+ }
883
+ }()
866
884
867
885
loop:
868
886
for {
@@ -929,6 +947,7 @@ loop:
929
947
}
930
948
eventCount ++
931
949
if exitOnWatchListBookmarkReceived && watchListBookmarkReceived {
950
+ stopWatcher = false
932
951
watchDuration := clock .Since (start )
933
952
klog .FromContext (ctx ).V (4 ).Info ("Exiting watch because received the bookmark that marks the end of initial events stream" , "reflector" , name , "totalItems" , eventCount , "duration" , watchDuration )
934
953
return watchListBookmarkReceived , nil
0 commit comments