@@ -125,7 +125,7 @@ type watchCache struct {
125
125
126
126
// This handler is run at the end of every Add/Update/Delete method
127
127
// and additionally gets the previous value of the object.
128
- onEvent func (* watchCacheEvent )
128
+ eventHandler func (* watchCacheEvent )
129
129
130
130
// for testing timeouts.
131
131
clock clock.Clock
@@ -137,6 +137,7 @@ type watchCache struct {
137
137
func newWatchCache (
138
138
capacity int ,
139
139
keyFunc func (runtime.Object ) (string , error ),
140
+ eventHandler func (* watchCacheEvent ),
140
141
getAttrsFunc func (runtime.Object ) (labels.Set , fields.Set , error ),
141
142
versioner storage.Versioner ) * watchCache {
142
143
wc := & watchCache {
@@ -149,6 +150,7 @@ func newWatchCache(
149
150
store : cache .NewStore (storeElementKey ),
150
151
resourceVersion : 0 ,
151
152
listResourceVersion : 0 ,
153
+ eventHandler : eventHandler ,
152
154
clock : clock.RealClock {},
153
155
versioner : versioner ,
154
156
}
@@ -204,6 +206,8 @@ func (w *watchCache) objectToVersionedRuntimeObject(obj interface{}) (runtime.Ob
204
206
return object , resourceVersion , nil
205
207
}
206
208
209
+ // processEvent is safe as long as there is at most one call to it in flight
210
+ // at any point in time.
207
211
func (w * watchCache ) processEvent (event watch.Event , resourceVersion uint64 , updateFunc func (* storeElement ) error ) error {
208
212
key , err := w .keyFunc (event .Object )
209
213
if err != nil {
@@ -224,30 +228,41 @@ func (w *watchCache) processEvent(event watch.Event, resourceVersion uint64, upd
224
228
ResourceVersion : resourceVersion ,
225
229
}
226
230
227
- // TODO: We should consider moving this lock below after the watchCacheEvent
228
- // is created. In such situation, the only problematic scenario is Replace(
229
- // happening after getting object from store and before acquiring a lock.
230
- // Maybe introduce another lock for this purpose.
231
- w .Lock ()
232
- defer w .Unlock ()
233
- previous , exists , err := w .store .Get (elem )
234
- if err != nil {
231
+ if err := func () error {
232
+ // TODO: We should consider moving this lock below after the watchCacheEvent
233
+ // is created. In such situation, the only problematic scenario is Replace(
234
+ // happening after getting object from store and before acquiring a lock.
235
+ // Maybe introduce another lock for this purpose.
236
+ w .Lock ()
237
+ defer w .Unlock ()
238
+
239
+ previous , exists , err := w .store .Get (elem )
240
+ if err != nil {
241
+ return err
242
+ }
243
+ if exists {
244
+ previousElem := previous .(* storeElement )
245
+ watchCacheEvent .PrevObject = previousElem .Object
246
+ watchCacheEvent .PrevObjLabels = previousElem .Labels
247
+ watchCacheEvent .PrevObjFields = previousElem .Fields
248
+ }
249
+
250
+ w .updateCache (watchCacheEvent )
251
+ w .resourceVersion = resourceVersion
252
+ defer w .cond .Broadcast ()
253
+
254
+ return updateFunc (elem )
255
+ }(); err != nil {
235
256
return err
236
257
}
237
- if exists {
238
- previousElem := previous .(* storeElement )
239
- watchCacheEvent .PrevObject = previousElem .Object
240
- watchCacheEvent .PrevObjLabels = previousElem .Labels
241
- watchCacheEvent .PrevObjFields = previousElem .Fields
242
- }
243
- w .updateCache (watchCacheEvent )
244
- w .resourceVersion = resourceVersion
245
258
246
- if w .onEvent != nil {
247
- w .onEvent (watchCacheEvent )
259
+ // Avoid calling event handler under lock.
260
+ // This is safe as long as there is at most one call to processEvent in flight
261
+ // at any point in time.
262
+ if w .eventHandler != nil {
263
+ w .eventHandler (watchCacheEvent )
248
264
}
249
- w .cond .Broadcast ()
250
- return updateFunc (elem )
265
+ return nil
251
266
}
252
267
253
268
// Assumes that lock is already held for write.
@@ -397,12 +412,6 @@ func (w *watchCache) SetOnReplace(onReplace func()) {
397
412
w .onReplace = onReplace
398
413
}
399
414
400
- func (w * watchCache ) SetOnEvent (onEvent func (* watchCacheEvent )) {
401
- w .Lock ()
402
- defer w .Unlock ()
403
- w .onEvent = onEvent
404
- }
405
-
406
415
func (w * watchCache ) GetAllEventsSinceThreadUnsafe (resourceVersion uint64 ) ([]* watchCacheEvent , error ) {
407
416
size := w .endIndex - w .startIndex
408
417
var oldest uint64
0 commit comments