aboutsummaryrefslogtreecommitdiffhomepage
path: root/cache
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <[email protected]>2024-05-03 11:04:57 +0200
committerBjørn Erik Pedersen <[email protected]>2024-05-04 19:45:43 +0200
commit503d20954f10507b9b43c6ee1c38001e53cf0b14 (patch)
tree06e1aeddd995c2b8ff2fb48c0879187b2b819e4b /cache
parent68e95327f7be941c44c256d2dac74ea96e731674 (diff)
downloadhugo-503d20954f10507b9b43c6ee1c38001e53cf0b14.tar.gz
hugo-503d20954f10507b9b43c6ee1c38001e53cf0b14.zip
Make the cache eviction logic for stale entities more robust
Fixes #12458
Diffstat (limited to 'cache')
-rw-r--r--cache/dynacache/dynacache.go34
-rw-r--r--cache/dynacache/dynacache_test.go12
2 files changed, 35 insertions, 11 deletions
diff --git a/cache/dynacache/dynacache.go b/cache/dynacache/dynacache.go
index 87ef68f5b..6190dd234 100644
--- a/cache/dynacache/dynacache.go
+++ b/cache/dynacache/dynacache.go
@@ -385,13 +385,37 @@ type Partition[K comparable, V any] struct {
// GetOrCreate gets or creates a value for the given key.
func (p *Partition[K, V]) GetOrCreate(key K, create func(key K) (V, error)) (V, error) {
+ v, err := p.doGetOrCreate(key, create)
+ if err != nil {
+ return p.zero, err
+ }
+ if resource.StaleVersion(v) > 0 {
+ p.c.Delete(key)
+ return p.doGetOrCreate(key, create)
+ }
+ return v, err
+}
+
+func (p *Partition[K, V]) doGetOrCreate(key K, create func(key K) (V, error)) (V, error) {
v, _, err := p.c.GetOrCreate(key, create)
return v, err
}
+func (p *Partition[K, V]) GetOrCreateWitTimeout(key K, duration time.Duration, create func(key K) (V, error)) (V, error) {
+ v, err := p.doGetOrCreateWitTimeout(key, duration, create)
+ if err != nil {
+ return p.zero, err
+ }
+ if resource.StaleVersion(v) > 0 {
+ p.c.Delete(key)
+ return p.doGetOrCreateWitTimeout(key, duration, create)
+ }
+ return v, err
+}
+
// GetOrCreateWitTimeout gets or creates a value for the given key and times out if the create function
// takes too long.
-func (p *Partition[K, V]) GetOrCreateWitTimeout(key K, duration time.Duration, create func(key K) (V, error)) (V, error) {
+func (p *Partition[K, V]) doGetOrCreateWitTimeout(key K, duration time.Duration, create func(key K) (V, error)) (V, error) {
resultch := make(chan V, 1)
errch := make(chan error, 1)
@@ -448,7 +472,7 @@ func (p *Partition[K, V]) clearOnRebuild(changeset ...identity.Identity) {
shouldDelete := func(key K, v V) bool {
// We always clear elements marked as stale.
- if resource.IsStaleAny(v) {
+ if resource.StaleVersion(v) > 0 {
return true
}
@@ -503,8 +527,8 @@ func (p *Partition[K, V]) Keys() []K {
func (p *Partition[K, V]) clearStale() {
p.c.DeleteFunc(func(key K, v V) bool {
- isStale := resource.IsStaleAny(v)
- if isStale {
+ staleVersion := resource.StaleVersion(v)
+ if staleVersion > 0 {
p.trace.Log(
logg.StringFunc(
func() string {
@@ -514,7 +538,7 @@ func (p *Partition[K, V]) clearStale() {
)
}
- return isStale
+ return staleVersion > 0
})
}
diff --git a/cache/dynacache/dynacache_test.go b/cache/dynacache/dynacache_test.go
index 275e63f0b..a58a8d94b 100644
--- a/cache/dynacache/dynacache_test.go
+++ b/cache/dynacache/dynacache_test.go
@@ -29,12 +29,12 @@ var (
)
type testItem struct {
- name string
- isStale bool
+ name string
+ staleVersion uint32
}
-func (t testItem) IsStale() bool {
- return t.isStale
+func (t testItem) StaleVersion() uint32 {
+ return t.staleVersion
}
func (t testItem) IdentifierBase() string {
@@ -109,7 +109,7 @@ func newTestCache(t *testing.T) *Cache {
p2.GetOrCreate("clearBecauseStale", func(string) (testItem, error) {
return testItem{
- isStale: true,
+ staleVersion: 32,
}, nil
})
@@ -121,7 +121,7 @@ func newTestCache(t *testing.T) *Cache {
p2.GetOrCreate("clearNever", func(string) (testItem, error) {
return testItem{
- isStale: false,
+ staleVersion: 0,
}, nil
})