Skip to content

Commit ac380d6

Browse files
authored
Merge pull request #1165 from vincepri/backpor06-1163
[0.6] 🐛 Controller.Watch() should not store watches if already started
2 parents 29c2e32 + 78d0026 commit ac380d6

File tree

2 files changed

+20
-11
lines changed

2 files changed

+20
-11
lines changed

pkg/internal/controller/controller.go

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@ type Controller struct {
7171

7272
// TODO(community): Consider initializing a logger with the Controller Name as the tag
7373

74-
// watches maintains a list of sources, handlers, and predicates to start when the controller is started.
75-
watches []watchDescription
74+
// startWatches maintains a list of sources, handlers, and predicates to start when the controller is started.
75+
startWatches []watchDescription
7676

7777
// Log is used to log messages to users during reconciliation, or for example when a watch is started.
7878
Log logr.Logger
@@ -108,13 +108,16 @@ func (c *Controller) Watch(src source.Source, evthdler handler.EventHandler, prc
108108
}
109109
}
110110

111-
c.watches = append(c.watches, watchDescription{src: src, handler: evthdler, predicates: prct})
112-
if c.Started {
113-
c.Log.Info("Starting EventSource", "source", src)
114-
return src.Start(evthdler, c.Queue, prct...)
111+
// Controller hasn't started yet, store the watches locally and return.
112+
//
113+
// These watches are going to be held on the controller struct until the manager or user calls Start(...).
114+
if !c.Started {
115+
c.startWatches = append(c.startWatches, watchDescription{src: src, handler: evthdler, predicates: prct})
116+
return nil
115117
}
116118

117-
return nil
119+
c.Log.Info("Starting EventSource", "source", src)
120+
return src.Start(evthdler, c.Queue, prct...)
118121
}
119122

120123
// Start implements controller.Controller
@@ -135,7 +138,7 @@ func (c *Controller) Start(stop <-chan struct{}) error {
135138
// NB(directxman12): launch the sources *before* trying to wait for the
136139
// caches to sync so that they have a chance to register their intendeded
137140
// caches.
138-
for _, watch := range c.watches {
141+
for _, watch := range c.startWatches {
139142
c.Log.Info("Starting EventSource", "source", watch.src)
140143
if err := watch.src.Start(watch.handler, c.Queue, watch.predicates...); err != nil {
141144
return err
@@ -145,7 +148,7 @@ func (c *Controller) Start(stop <-chan struct{}) error {
145148
// Start the SharedIndexInformer factories to begin populating the SharedIndexInformer caches
146149
c.Log.Info("Starting Controller")
147150

148-
for _, watch := range c.watches {
151+
for _, watch := range c.startWatches {
149152
syncingSource, ok := watch.src.(source.SyncingSource)
150153
if !ok {
151154
continue
@@ -159,6 +162,12 @@ func (c *Controller) Start(stop <-chan struct{}) error {
159162
}
160163
}
161164

165+
// All the watches have been started, we can reset the local slice.
166+
//
167+
// We should never hold watches more than necessary, each watch source can hold a backing cache,
168+
// which won't be garbage collected if we hold a reference to it.
169+
c.startWatches = nil
170+
162171
if c.JitterPeriod == 0 {
163172
c.JitterPeriod = 1 * time.Second
164173
}

pkg/internal/controller/controller_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ var _ = Describe("controller", func() {
9191
Describe("Start", func() {
9292
It("should return an error if there is an error waiting for the informers", func(done Done) {
9393
f := false
94-
ctrl.watches = []watchDescription{{
94+
ctrl.startWatches = []watchDescription{{
9595
src: source.NewKindWithCache(&corev1.Pod{}, &informertest.FakeInformers{Synced: &f}),
9696
}}
9797
ctrl.Name = "foo"
@@ -115,7 +115,7 @@ var _ = Describe("controller", func() {
115115
Expect(err).NotTo(HaveOccurred())
116116
_, err = c.GetInformer(context.TODO(), &appsv1.ReplicaSet{})
117117
Expect(err).NotTo(HaveOccurred())
118-
ctrl.watches = []watchDescription{{
118+
ctrl.startWatches = []watchDescription{{
119119
src: source.NewKindWithCache(&appsv1.Deployment{}, &informertest.FakeInformers{}),
120120
}}
121121

0 commit comments

Comments
 (0)