fix(namespace): harden lifecycle — RemoveNamespace, parallel dispatch, reconciler

- DefaultNSResolver.RemoveNamespace(): removes NS from global map on label removal
  so Snapshot() and idleObjectReaper stop iterating deleted namespaces.
  Fixes class of dirty-state bugs when NS name is reused by new tenant.

- HandleWatcherNamespaceRemoval: call RemoveNamespace on both TrackOnly and
  DispatchRemove strategies — global resolver cleanup is always required.

- dispatch(): parallel subscriber execution via goroutine per subscriber +
  sync.WaitGroup. Reduces onboarding latency from O(N_subscribers × API_latency)
  to O(max(API_latency)). Safe: MarkPart* are internally mutex-protected.

- inMemoryNamespaceManager.RunReconciler(): 30s ticker scans for
  NamespacePhaseFailed records and retries via DispatchResync. Started
  automatically by RunManagedNamespaceWatcher. Fixes permanent stuck-failed
  state caused by transient k8s API errors.

Analysis source: FORENSIC_ARCHITECTURE_AUDIT.md §Deep Risk Analysis
This commit is contained in:
“Naeel”
2026-05-18 08:45:31 +04:00
parent 4c82285863
commit 3b93c5dc8b
5 changed files with 479 additions and 17 deletions
+17
View File
@@ -113,6 +113,23 @@ func (nsr *NamespaceResolver) AddNamespace(ns string) bool {
return true
}
// RemoveNamespace removes a namespace from FissionResourceNS.
// Returns true if the namespace was present and removed, false if it was not found.
// Thread-safe. Used when a namespace loses the fission.io/managed=true label so that
// Snapshot() and idleObjectReaper loops no longer iterate over deleted namespaces.
func (nsr *NamespaceResolver) RemoveNamespace(ns string) bool {
nsr.mu.Lock()
defer nsr.mu.Unlock()
if _, exists := nsr.FissionResourceNS[ns]; !exists {
return false
}
delete(nsr.FissionResourceNS, ns)
if nsr.Logger != nil {
nsr.Logger.Info("dynamically removed namespace from resolver", zap.String("namespace", ns))
}
return true
}
// Snapshot returns a stable copy of the currently registered resource namespaces.
// The returned slice is detached from the internal mutable map and safe to iterate.
func (nsr *NamespaceResolver) Snapshot() []string {