@@ -262,6 +262,30 @@ func (o *operator) worker(ctx context.Context, loop *QueueInformer) {
262262}
263263
264264func (o * operator ) processNextWorkItem (ctx context.Context , loop * QueueInformer ) bool {
265+ // **************************** WARNING ****************************
266+ // The QueueInformer listens to resource events raised by its
267+ // (client-go) informer. For Add/Update event, it extracts the key
268+ // for the resource and adds to its queue (that we Get() from below)
269+ // a ResourceEvent carrying the key.
270+ // **Except** if it is a deletion event. In that case,
271+ // ResourceEvent carries the resource object (or tombstone).
272+ // The sync'er expects a ResourceEvent carrying the resource.
273+ // So, in the case of an Add/Update event coming from the queue,
274+ // the resource is acquired from the index (through the key), and then
275+ // a ResourceEvent carrying the resource is handed to the syncer.
276+ // It should also be noted that throughout the code, items are added to
277+ // queueinformers out of band of informer notifications.
278+ // The fact that the queueinformers queue processes ResourceEvents, which
279+ // themselves encapsulate an interface{} "Resource" make it tricky for the
280+ // queue to dedup. Previous to the writing of this comment, the queue was
281+ // processing strings and ResourceEvents, which led to concurrent processing
282+ // of the same resource. To address this, we enforce (with panic) that the resource
283+ // in the ResourceEvent must either be a cache.ExplicitKey or a client.Object.
284+ // We then make sure that the ResourceEvent's String() returns the key for the
285+ // encapsulated resource. Thus, independent of the resource type, the queue always
286+ // processes it by key and dedups appropriately.
287+ // Furthermore, we also enforce here that Add/Update events always contain
288+ // cache.ExplicitKey as their Resource
265289 queue := loop .queue
266290 item , quit := queue .Get ()
267291
@@ -271,28 +295,23 @@ func (o *operator) processNextWorkItem(ctx context.Context, loop *QueueInformer)
271295 defer queue .Done (item )
272296
273297 logger := o .logger .WithField ("item" , item )
274- logger .WithField ("queue-length" , queue .Len ()).Trace ("popped queue" )
298+ logger .WithField ("queue-length" , queue .Len ()).Info ("popped queue" )
275299
276300 var event = item
277301 if item .Type () != kubestate .ResourceDeleted {
278- // Get the key
279- //key, keyable := loop.key(item)
280- //if !keyable {
281- // logger.WithField("item", item).Warn("could not form key")
282- // queue.Forget(item)
283- // return true
284- //}
285- key , ok := item .Resource ().(string )
286- if ! ok {
287- panic (fmt .Sprintf ("unexpected item resource type: %T" , item .Resource ()))
302+ key , keyable := loop .key (item )
303+ if ! keyable {
304+ logger .WithField ("item" , item ).Warn ("could not form key" )
305+ queue .Forget (item )
306+ return true
288307 }
289308
290309 logger = logger .WithField ("cache-key" , key )
291310
292311 // Get the current cached version of the resource
293312 var exists bool
294313 var err error
295- resource , exists , err := loop .indexer .GetByKey (key )
314+ resource , exists , err := loop .indexer .GetByKey (string ( key ) )
296315 if err != nil {
297316 logger .WithError (err ).Error ("cache get failed" )
298317 queue .Forget (item )
0 commit comments