mirror of
https://github.com/open-policy-agent/opa.git
synced 2026-08-12 19:32:48 -06:00
bfd0d00073
AnnotationSet.MergedLabels was introduced in v1.17.0 to cache merged label maps per rule. It used weak.Pointer[Rule] as the cache key and registered a runtime.AddCleanup to evict the entry when the rule was garbage-collected. The cleanup closure captured `as` (the AnnotationSet pointer). The AnnotationSet holds strong references to every module it was built from (as.modules), and each module holds its rules. This meant that once any rule had a cleanup registered: runtime cleanup queue → closure → AnnotationSet → modules → Rule Rule was always reachable through that path, so the cleanup could never fire. Nothing would ever delete the closure, so the AnnotationSet and all of its rules were permanently retained. In practice, OPA's dynamic bundle plugin recompiles policies on every poll cycle. Each compilation creates a fresh AnnotationSet. With the bug, old AnnotationSets accumulated in the heap indefinitely, causing the OOM-kill pattern reported in #8817. Fix: drop the cache entirely. MergedLabels now calls Chain and mergeChainLabels on every invocation. Chain is a handful of map lookups and MergedLabels is called at most once per evaluated rule per request, so the recomputation cost is negligible. This removes the mergedLabels sync.Map field, the ruleLabelsEntry type, and the runtime/sync/weak imports. A regression test uses weak.Pointer[AnnotationSet] to assert that an AnnotationSet is collectable after it goes out of scope. Fixes #8817 Signed-off-by: Stephan Renatus <stephan.renatus@gmail.com>