From 503d20954f10507b9b43c6ee1c38001e53cf0b14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Fri, 3 May 2024 11:04:57 +0200 Subject: Make the cache eviction logic for stale entities more robust Fixes #12458 --- resources/resource.go | 17 ++++++++++------- resources/resource/resourcetypes.go | 24 +++++++++++++++++------- resources/transform.go | 5 +++-- 3 files changed, 30 insertions(+), 16 deletions(-) (limited to 'resources') diff --git a/resources/resource.go b/resources/resource.go index 867b262fb..0fee69cdd 100644 --- a/resources/resource.go +++ b/resources/resource.go @@ -296,16 +296,19 @@ type hashProvider interface { hash() string } +var _ resource.StaleInfo = (*StaleValue[any])(nil) + type StaleValue[V any] struct { // The value. Value V - // IsStaleFunc reports whether the value is stale. - IsStaleFunc func() bool + // StaleVersionFunc reports the current version of the value. + // This always starts out at 0 and get incremented on staleness. + StaleVersionFunc func() uint32 } -func (s *StaleValue[V]) IsStale() bool { - return s.IsStaleFunc() +func (s *StaleValue[V]) StaleVersion() uint32 { + return s.StaleVersionFunc() } type AtomicStaler struct { @@ -313,11 +316,11 @@ type AtomicStaler struct { } func (s *AtomicStaler) MarkStale() { - atomic.StoreUint32(&s.stale, 1) + atomic.AddUint32(&s.stale, 1) } -func (s *AtomicStaler) IsStale() bool { - return atomic.LoadUint32(&(s.stale)) > 0 +func (s *AtomicStaler) StaleVersion() uint32 { + return atomic.LoadUint32(&(s.stale)) } // For internal use. diff --git a/resources/resource/resourcetypes.go b/resources/resource/resourcetypes.go index 0766fe232..5d9533223 100644 --- a/resources/resource/resourcetypes.go +++ b/resources/resource/resourcetypes.go @@ -233,17 +233,27 @@ type StaleMarker interface { // StaleInfo tells if a resource is marked as stale. type StaleInfo interface { - IsStale() bool + StaleVersion() uint32 } -// IsStaleAny reports whether any of the os is marked as stale. -func IsStaleAny(os ...any) bool { - for _, o := range os { - if s, ok := o.(StaleInfo); ok && s.IsStale() { - return true +// StaleVersion returns the StaleVersion for the given os, +// or 0 if not set. +func StaleVersion(os any) uint32 { + if s, ok := os.(StaleInfo); ok { + return s.StaleVersion() + } + return 0 +} + +// StaleVersionSum calculates the sum of the StaleVersionSum for the given oss. +func StaleVersionSum(oss ...any) uint32 { + var version uint32 + for _, o := range oss { + if s, ok := o.(StaleInfo); ok && s.StaleVersion() > 0 { + version += s.StaleVersion() } } - return false + return version } // MarkStale will mark any of the oses as stale, if possible. diff --git a/resources/transform.go b/resources/transform.go index d9084b178..b498924f5 100644 --- a/resources/transform.go +++ b/resources/transform.go @@ -657,8 +657,9 @@ type resourceAdapterInner struct { *publishOnce } -func (r *resourceAdapterInner) IsStale() bool { - return r.Staler.IsStale() || r.target.IsStale() +func (r *resourceAdapterInner) StaleVersion() uint32 { + // Both of these are incremented on change. + return r.Staler.StaleVersion() + r.target.StaleVersion() } type resourceTransformations struct { -- cgit v1.2.3