@@ -231,15 +231,18 @@ func (p *Provider) handleSecret(ctx context.Context, secret *corev1.Secret, mgr
231
231
return fmt .Errorf ("failed to create cluster: %w" , err )
232
232
}
233
233
234
- // Apply any field indexers
234
+ // Copy indexers to avoid holding lock.
235
235
p .lock .RLock ()
236
- for _ , idx := range p .indexers {
236
+ indexers := make ([]index , len (p .indexers ))
237
+ copy (indexers , p .indexers )
238
+ p .lock .RUnlock ()
239
+
240
+ // Apply any field indexers
241
+ for _ , idx := range indexers {
237
242
if err := cl .GetFieldIndexer ().IndexField (ctx , idx .object , idx .field , idx .extractValue ); err != nil {
238
- p .lock .RUnlock ()
239
243
return fmt .Errorf ("failed to index field %q: %w" , idx .field , err )
240
244
}
241
245
}
242
- p .lock .RUnlock ()
243
246
244
247
// Create a context that will be canceled when this cluster is removed
245
248
clusterCtx , cancel := context .WithCancel (ctx )
@@ -309,32 +312,27 @@ func (p *Provider) removeCluster(clusterName string) error {
309
312
log := p .log .WithValues ("cluster" , clusterName )
310
313
log .Info ("Removing cluster" )
311
314
312
- // Find the cluster and cancel function
313
- p .lock .RLock ()
315
+ p .lock .Lock ()
314
316
ac , exists := p .clusters [clusterName ]
315
317
if ! exists {
316
- p .lock .RUnlock ()
317
- return fmt .Errorf ("cluster %s not found" , clusterName )
318
+ p .lock .Unlock ()
319
+ return fmt .Errorf ("cluster not found" )
318
320
}
319
- p .lock .RUnlock ()
321
+ delete (p .clusters , clusterName )
322
+ p .lock .Unlock ()
320
323
321
- // Cancel the context to trigger cleanup for this cluster
324
+ // Cancel the context to trigger cleanup for this cluster.
325
+ // This is done outside the lock to avoid holding the lock for a long time.
322
326
ac .Cancel ()
323
327
log .Info ("Cancelled cluster context" )
324
328
325
- // Clean up our maps
326
- p .lock .Lock ()
327
- delete (p .clusters , clusterName )
328
- p .lock .Unlock ()
329
-
330
329
log .Info ("Successfully removed cluster" )
331
330
return nil
332
331
}
333
332
334
333
// IndexField indexes a field on all clusters, existing and future.
335
334
func (p * Provider ) IndexField (ctx context.Context , obj client.Object , field string , extractValue client.IndexerFunc ) error {
336
335
p .lock .Lock ()
337
- defer p .lock .Unlock ()
338
336
339
337
// Save for future clusters
340
338
p .indexers = append (p .indexers , index {
@@ -343,9 +341,16 @@ func (p *Provider) IndexField(ctx context.Context, obj client.Object, field stri
343
341
extractValue : extractValue ,
344
342
})
345
343
346
- // Apply to existing clusters
344
+ // Create a copy of the clusters to avoid holding the lock.
345
+ clustersSnapshot := make (map [string ]cluster.Cluster , len (p .clusters ))
347
346
for name , ac := range p .clusters {
348
- if err := ac .Cluster .GetFieldIndexer ().IndexField (ctx , obj , field , extractValue ); err != nil {
347
+ clustersSnapshot [name ] = ac .Cluster
348
+ }
349
+ p .lock .Unlock ()
350
+
351
+ // Apply to existing clusters
352
+ for name , cl := range clustersSnapshot {
353
+ if err := cl .GetFieldIndexer ().IndexField (ctx , obj , field , extractValue ); err != nil {
349
354
return fmt .Errorf ("failed to index field %q on cluster %q: %w" , field , name , err )
350
355
}
351
356
}
0 commit comments