Skip to content

Commit b67bc65

Browse files
committed
Address comments.
1 parent 43118a3 commit b67bc65

File tree

5 files changed

+30
-16
lines changed

5 files changed

+30
-16
lines changed

pkg/config/controller.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,14 @@ type Controller struct {
6060
// Defaults to true, which means the controller will use leader election.
6161
NeedLeaderElection *bool
6262

63-
// NeedWarmup indicates whether the controller needs to use warm up.
64-
// Defaults to false, which means the controller will not use warm up.
63+
// NeedWarmup specifies whether the controller should start its sources when the manager is not
64+
// the leader. This is useful for cases where sources take a long time to start, as it allows
65+
// for the controller to warm up its caches even before it is elected as the leader. This
66+
// improves leadership failover time, as the caches will be prepopulated before the controller
67+
// transitions to be leader.
68+
//
69+
// When set to true, the controller will start its sources without transitioning to be leader.
70+
// Defaults to false.
6571
NeedWarmup *bool
6672

6773
// UsePriorityQueue configures the controllers queue to use the controller-runtime provided

pkg/controller/controller.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
/*
2-
Copyright 2018 The Kubernetes Authors.
1+
/* Copyright 2018 The Kubernetes Authors.
32
43
Licensed under the Apache License, Version 2.0 (the "License");
54
you may not use this file except in compliance with the License.
@@ -95,9 +94,12 @@ type TypedOptions[request comparable] struct {
9594
UsePriorityQueue *bool
9695

9796
// NeedWarmup specifies whether the controller should start its sources when the manager is not
98-
// the leader. When set to true, the controller will not restart its sources when/if it
97+
// the leader. This is useful for cases where sources take a long time to start, as it allows
98+
// for the controller to warm up its caches even before it is elected as the leader. This
99+
// improves leadership failover time, as the caches will be prepopulated before the controller
99100
// transitions to be leader.
100101
//
102+
// When set to true, the controller will start its sources without transitioning to be leader.
101103
// Defaults to false.
102104
NeedWarmup *bool
103105
}

pkg/internal/controller/controller.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -170,10 +170,8 @@ func (c *Controller[request]) NeedLeaderElection() bool {
170170
// Warmup implements the manager.WarmupRunnable interface.
171171
func (c *Controller[request]) Warmup(ctx context.Context) error {
172172
if c.NeedWarmup == nil || !*c.NeedWarmup {
173-
c.didEventSourcesFinishSync.Store(ptr.To(true))
174173
return nil
175174
}
176-
177175
return c.startEventSources(ctx)
178176
}
179177

@@ -291,7 +289,6 @@ func (c *Controller[request]) startEventSources(ctx context.Context) error {
291289
_, ok := watch.(interface {
292290
String() string
293291
})
294-
295292
if !ok {
296293
log = log.WithValues("source", fmt.Sprintf("%T", watch))
297294
} else {

pkg/internal/controller/controller_test.go

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"errors"
2222
"fmt"
2323
"sync"
24+
"sync/atomic"
2425
"time"
2526

2627
"github.com/go-logr/logr"
@@ -1062,32 +1063,38 @@ var _ = Describe("controller", func() {
10621063
})
10631064
})
10641065

1065-
Describe("Warmup without warmup enabled", func() {
1066+
Describe("Warmup with warmup disabled", func() {
10661067
JustBeforeEach(func() {
10671068
ctrl.NeedWarmup = ptr.To(false)
10681069
})
10691070

1070-
It("should not start sources if warmup is disabled.", func() {
1071+
It("should not start sources when Warmup is called if warmup is disabled but start it when Start is called.", func() {
10711072
// Setup controller with sources that complete successfully
10721073
ctx, cancel := context.WithCancel(context.Background())
10731074
defer cancel()
10741075

10751076
ctrl.CacheSyncTimeout = time.Second
1076-
isSourceStarted := false
1077+
var isSourceStarted atomic.Bool
1078+
isSourceStarted.Store(false)
10771079
ctrl.startWatches = []source.TypedSource[reconcile.Request]{
10781080
source.Func(func(ctx context.Context, _ workqueue.TypedRateLimitingInterface[reconcile.Request]) error {
1079-
isSourceStarted = true
1081+
isSourceStarted.Store(true)
10801082
return nil
10811083
}),
10821084
}
10831085

1086+
By("Calling Warmup when NeedWarmup is false")
10841087
err := ctrl.Warmup(ctx)
10851088
Expect(err).NotTo(HaveOccurred())
1089+
Expect(isSourceStarted.Load()).To(BeFalse())
10861090

1087-
result := ctrl.DidFinishWarmup(ctx)
1088-
Expect(result).To(BeTrue())
1089-
1090-
Expect(isSourceStarted).To(BeFalse())
1091+
By("Calling Start when NeedWarmup is false")
1092+
// Now call Start
1093+
go func() {
1094+
defer GinkgoRecover()
1095+
Expect(ctrl.Start(ctx)).To(Succeed())
1096+
}()
1097+
Eventually(func() bool { return isSourceStarted.Load() }).Should(BeTrue())
10911098
})
10921099
})
10931100
})

pkg/manager/manager.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,8 @@ type LeaderElectionRunnable interface {
316316

317317
// WarmupRunnable knows if a Runnable should be a warmup runnable. A warmup runnable is a runnable
318318
// that should be run when the manager is started, but before the leader election is acquired.
319+
// Note: Implementing this interface is only useful when LeaderElection is enabled, as the behavior
320+
// without leaderelection is to run LeaderElectionRunnables immediately.
319321
type WarmupRunnable interface {
320322
// Warmup is the implementation of the warmup runnable.
321323
Warmup(context.Context) error

0 commit comments

Comments
 (0)