summaryrefslogtreecommitdiffstats
path: root/cache
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2024-02-02 11:20:08 +0100
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2024-02-04 16:55:06 +0100
commit609d798e342c873143cf7ad05e987f3d8f7fbb45 (patch)
treea47532d5ba4acf3f12aad25791ee24ff802af35e /cache
parent53f204310ec8362d7084c123e8e16f5bb73dd257 (diff)
Handle resource changes when the resources is already evicted from cache
Also fix a logical flaw in the cache resizer that made it too aggressive. After this I haven't been able to reproduce #11988, but I need to look closer. Closes #11973 Updates #11988
Diffstat (limited to 'cache')
-rw-r--r--cache/dynacache/dynacache.go50
1 files changed, 41 insertions, 9 deletions
diff --git a/cache/dynacache/dynacache.go b/cache/dynacache/dynacache.go
index bb3f7b098..85b360138 100644
--- a/cache/dynacache/dynacache.go
+++ b/cache/dynacache/dynacache.go
@@ -25,6 +25,7 @@ import (
"github.com/bep/lazycache"
"github.com/bep/logg"
+ "github.com/gohugoio/hugo/common/collections"
"github.com/gohugoio/hugo/common/herrors"
"github.com/gohugoio/hugo/common/loggers"
"github.com/gohugoio/hugo/common/paths"
@@ -63,11 +64,26 @@ func New(opts Options) *Cache {
infol := opts.Log.InfoCommand("dynacache")
+ evictedIdentities := collections.NewStack[identity.Identity]()
+
+ onEvict := func(k, v any) {
+ if !opts.Running {
+ return
+ }
+ identity.WalkIdentitiesShallow(v, func(level int, id identity.Identity) bool {
+ evictedIdentities.Push(id)
+ return false
+ })
+ resource.MarkStale(v)
+ }
+
c := &Cache{
- partitions: make(map[string]PartitionManager),
- opts: opts,
- stats: stats,
- infol: infol,
+ partitions: make(map[string]PartitionManager),
+ onEvict: onEvict,
+ evictedIdentities: evictedIdentities,
+ opts: opts,
+ stats: stats,
+ infol: infol,
}
c.stop = c.start()
@@ -106,14 +122,23 @@ type Cache struct {
mu sync.RWMutex
partitions map[string]PartitionManager
- opts Options
- infol logg.LevelLogger
+
+ onEvict func(k, v any)
+ evictedIdentities *collections.Stack[identity.Identity]
+
+ opts Options
+ infol logg.LevelLogger
stats *stats
stopOnce sync.Once
stop func()
}
+// DrainEvictedIdentities drains the evicted identities from the cache.
+func (c *Cache) DrainEvictedIdentities() []identity.Identity {
+ return c.evictedIdentities.Drain()
+}
+
// ClearMatching clears all partition for which the predicate returns true.
func (c *Cache) ClearMatching(predicate func(k, v any) bool) {
g := rungroup.Run[PartitionManager](context.Background(), rungroup.Config[PartitionManager]{
@@ -318,9 +343,13 @@ func GetOrCreatePartition[K comparable, V any](c *Cache, name string, opts Optio
const numberOfPartitionsEstimate = 10
maxSize := opts.CalculateMaxSize(c.opts.MaxSize / numberOfPartitionsEstimate)
+ onEvict := func(k K, v V) {
+ c.onEvict(k, v)
+ }
+
// Create a new partition and cache it.
partition := &Partition[K, V]{
- c: lazycache.New(lazycache.Options[K, V]{MaxEntries: maxSize}),
+ c: lazycache.New(lazycache.Options[K, V]{MaxEntries: maxSize, OnEvict: onEvict}),
maxSize: maxSize,
trace: c.opts.Log.Logger().WithLevel(logg.LevelTrace).WithField("partition", name),
opts: opts,
@@ -445,7 +474,6 @@ func (p *Partition[K, V]) clearOnRebuild(changeset ...identity.Identity) {
},
),
)
- resource.MarkStale(v)
return true
}
return false
@@ -483,6 +511,10 @@ func (p *Partition[K, V]) adjustMaxSize(newMaxSize int) int {
if newMaxSize < minMaxSize {
newMaxSize = minMaxSize
}
+ oldMaxSize := p.maxSize
+ if newMaxSize == oldMaxSize {
+ return 0
+ }
p.maxSize = newMaxSize
// fmt.Println("Adjusting max size of partition from", oldMaxSize, "to", newMaxSize)
return p.c.Resize(newMaxSize)
@@ -535,7 +567,7 @@ type stats struct {
func (s *stats) adjustCurrentMaxSize() bool {
newCurrentMaxSize := int(math.Floor(float64(s.opts.MaxSize) * s.adjustmentFactor))
- if newCurrentMaxSize < s.opts.MaxSize {
+ if newCurrentMaxSize < s.opts.MinMaxSize {
newCurrentMaxSize = int(s.opts.MinMaxSize)
}
changed := newCurrentMaxSize != s.currentMaxSize