Skip to content

Commit 962ab1f

Browse files
authored
Merge pull request #371 from nvachhar/unsynced-informer-fix-option2
🐛 Ensure returned informers are always correctly synced
2 parents ea673b4 + 2ea3125 commit 962ab1f

File tree

1 file changed

+42
-47
lines changed

1 file changed

+42
-47
lines changed

pkg/cache/internal/informers_map.go

Lines changed: 42 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -147,68 +147,63 @@ func (ip *specificInformersMap) HasSyncedFuncs() []cache.InformerSynced {
147147
// the Informer from the map.
148148
func (ip *specificInformersMap) Get(gvk schema.GroupVersionKind, obj runtime.Object) (*MapEntry, error) {
149149
// Return the informer if it is found
150-
i, ok := func() (*MapEntry, bool) {
150+
i, started, ok := func() (*MapEntry, bool, bool) {
151151
ip.mu.RLock()
152152
defer ip.mu.RUnlock()
153153
i, ok := ip.informersByGVK[gvk]
154-
return i, ok
154+
return i, ip.started, ok
155155
}()
156-
if ok {
157-
return i, nil
158-
}
159-
160-
// Do the mutex part in its own function so we can use defer without blocking pieces that don't
161-
// need to be locked
162-
var sync bool
163-
i, err := func() (*MapEntry, error) {
164-
ip.mu.Lock()
165-
defer ip.mu.Unlock()
166156

167-
// Check the cache to see if we already have an Informer. If we do, return the Informer.
168-
// This is for the case where 2 routines tried to get the informer when it wasn't in the map
169-
// so neither returned early, but the first one created it.
170-
var ok bool
171-
i, ok := ip.informersByGVK[gvk]
172-
if ok {
173-
return i, nil
174-
}
175-
176-
// Create a NewSharedIndexInformer and add it to the map.
177-
var lw *cache.ListWatch
178-
lw, err := ip.createListWatcher(gvk, ip)
179-
if err != nil {
157+
if !ok {
158+
var err error
159+
if i, started, err = ip.addInformerToMap(gvk, obj); err != nil {
180160
return nil, err
181161
}
182-
ni := cache.NewSharedIndexInformer(lw, obj, ip.resync, cache.Indexers{
183-
cache.NamespaceIndex: cache.MetaNamespaceIndexFunc,
184-
})
185-
i = &MapEntry{
186-
Informer: ni,
187-
Reader: CacheReader{indexer: ni.GetIndexer(), groupVersionKind: gvk},
188-
}
189-
ip.informersByGVK[gvk] = i
190-
191-
// Start the Informer if need by
192-
// TODO(seans): write thorough tests and document what happens here - can you add indexers?
193-
// can you add eventhandlers?
194-
if ip.started {
195-
sync = true
196-
go i.Informer.Run(ip.stop)
197-
}
198-
return i, nil
199-
}()
200-
if err != nil {
201-
return nil, err
202162
}
203163

204-
if sync {
164+
if started && !i.Informer.HasSynced() {
205165
// Wait for it to sync before returning the Informer so that folks don't read from a stale cache.
206166
if !cache.WaitForCacheSync(ip.stop, i.Informer.HasSynced) {
207167
return nil, fmt.Errorf("failed waiting for %T Informer to sync", obj)
208168
}
209169
}
210170

211-
return i, err
171+
return i, nil
172+
}
173+
174+
func (ip *specificInformersMap) addInformerToMap(gvk schema.GroupVersionKind, obj runtime.Object) (*MapEntry, bool, error) {
175+
ip.mu.Lock()
176+
defer ip.mu.Unlock()
177+
178+
// Check the cache to see if we already have an Informer. If we do, return the Informer.
179+
// This is for the case where 2 routines tried to get the informer when it wasn't in the map
180+
// so neither returned early, but the first one created it.
181+
if i, ok := ip.informersByGVK[gvk]; ok {
182+
return i, ip.started, nil
183+
}
184+
185+
// Create a NewSharedIndexInformer and add it to the map.
186+
var lw *cache.ListWatch
187+
lw, err := ip.createListWatcher(gvk, ip)
188+
if err != nil {
189+
return nil, false, err
190+
}
191+
ni := cache.NewSharedIndexInformer(lw, obj, ip.resync, cache.Indexers{
192+
cache.NamespaceIndex: cache.MetaNamespaceIndexFunc,
193+
})
194+
i := &MapEntry{
195+
Informer: ni,
196+
Reader: CacheReader{indexer: ni.GetIndexer(), groupVersionKind: gvk},
197+
}
198+
ip.informersByGVK[gvk] = i
199+
200+
// Start the Informer if need by
201+
// TODO(seans): write thorough tests and document what happens here - can you add indexers?
202+
// can you add eventhandlers?
203+
if ip.started {
204+
go i.Informer.Run(ip.stop)
205+
}
206+
return i, ip.started, nil
212207
}
213208

214209
// newListWatch returns a new ListWatch object that can be used to create a SharedIndexInformer.

0 commit comments

Comments
 (0)