summaryrefslogtreecommitdiff
path: root/vendor/codeberg.org/gruf/go-cache/v3/result/cache.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/codeberg.org/gruf/go-cache/v3/result/cache.go')
-rw-r--r--vendor/codeberg.org/gruf/go-cache/v3/result/cache.go85
1 files changed, 60 insertions, 25 deletions
diff --git a/vendor/codeberg.org/gruf/go-cache/v3/result/cache.go b/vendor/codeberg.org/gruf/go-cache/v3/result/cache.go
index 805a4d989..5b16712b6 100644
--- a/vendor/codeberg.org/gruf/go-cache/v3/result/cache.go
+++ b/vendor/codeberg.org/gruf/go-cache/v3/result/cache.go
@@ -97,20 +97,22 @@ func (c *Cache[Value]) SetEvictionCallback(hook func(Value)) {
// Ensure non-nil hook.
hook = func(Value) {}
}
- c.cache.SetEvictionCallback(func(item *ttl.Entry[int64, result[Value]]) {
- for _, key := range item.Value.Keys {
+ c.cache.SetEvictionCallback(func(pkey int64, res result[Value]) {
+ c.cache.Lock()
+ for _, key := range res.Keys {
// Delete key->pkey lookup
pkeys := key.info.pkeys
delete(pkeys, key.key)
}
+ c.cache.Unlock()
- if item.Value.Error != nil {
+ if res.Error != nil {
// Skip error hooks
return
}
// Call user hook.
- hook(item.Value.Value)
+ hook(res.Value)
})
}
@@ -121,20 +123,22 @@ func (c *Cache[Value]) SetInvalidateCallback(hook func(Value)) {
hook = func(Value) {}
} // store hook.
c.invalid = hook
- c.cache.SetInvalidateCallback(func(item *ttl.Entry[int64, result[Value]]) {
- for _, key := range item.Value.Keys {
+ c.cache.SetInvalidateCallback(func(pkey int64, res result[Value]) {
+ c.cache.Lock()
+ for _, key := range res.Keys {
// Delete key->pkey lookup
pkeys := key.info.pkeys
delete(pkeys, key.key)
}
+ c.cache.Unlock()
- if item.Value.Error != nil {
+ if res.Error != nil {
// Skip error hooks
return
}
// Call user hook.
- hook(item.Value.Value)
+ hook(res.Value)
})
}
@@ -178,9 +182,17 @@ func (c *Cache[Value]) Load(lookup string, load func() (Value, error), keyParts
pkeys := keyInfo.pkeys[ckey]
if ok = (len(pkeys) > 0); ok {
+ var entry *ttl.Entry[int64, result[Value]]
+
// Fetch the result for primary key
- entry, _ := c.cache.Cache.Get(pkeys[0])
- res = entry.Value
+ entry, ok = c.cache.Cache.Get(pkeys[0])
+ if ok {
+ // Since the invalidation / eviction hooks acquire a mutex
+ // lock separately, and only at this point are the pkeys
+ // updated, there is a chance that a primary key may return
+ // no matching entry. Hence we have to check for it here.
+ res = entry.Value
+ }
}
// Done with lock
@@ -213,12 +225,19 @@ func (c *Cache[Value]) Load(lookup string, load func() (Value, error), keyParts
res.Keys = c.lookups.generate(res.Value)
}
+ var evict func()
+
// Acquire cache lock.
c.cache.Lock()
- defer c.cache.Unlock()
+ defer func() {
+ c.cache.Unlock()
+ if evict != nil {
+ evict()
+ }
+ }()
- // Cache result
- c.store(res)
+ // Store result in cache.
+ evict = c.store(res)
}
// Catch and return error
@@ -244,12 +263,19 @@ func (c *Cache[Value]) Store(value Value, store func() error) error {
Error: nil,
}
+ var evict func()
+
// Acquire cache lock.
c.cache.Lock()
- defer c.cache.Unlock()
+ defer func() {
+ c.cache.Unlock()
+ if evict != nil {
+ evict()
+ }
+ }()
- // Cache result
- c.store(result)
+ // Store result in cache.
+ evict = c.store(result)
// Call invalidate.
c.invalid(value)
@@ -278,9 +304,17 @@ func (c *Cache[Value]) Has(lookup string, keyParts ...any) bool {
pkeys := keyInfo.pkeys[ckey]
if ok = (len(pkeys) > 0); ok {
+ var entry *ttl.Entry[int64, result[Value]]
+
// Fetch the result for primary key
- entry, _ := c.cache.Cache.Get(pkeys[0])
- res = entry.Value
+ entry, ok = c.cache.Cache.Get(pkeys[0])
+ if ok {
+ // Since the invalidation / eviction hooks acquire a mutex
+ // lock separately, and only at this point are the pkeys
+ // updated, there is a chance that a primary key may return
+ // no matching entry. Hence we have to check for it here.
+ res = entry.Value
+ }
}
// Done with lock
@@ -301,19 +335,18 @@ func (c *Cache[Value]) Invalidate(lookup string, keyParts ...any) {
// Look for primary key for cache key
c.cache.Lock()
pkeys := keyInfo.pkeys[ckey]
+ delete(keyInfo.pkeys, ckey)
c.cache.Unlock()
- for _, pkey := range pkeys {
- // Invalidate each primary key
- c.cache.Invalidate(pkey)
- }
+ // Invalidate all primary keys.
+ c.cache.InvalidateAll(pkeys...)
}
// Clear empties the cache, calling the invalidate callback.
func (c *Cache[Value]) Clear() { c.cache.Clear() }
// store will cache this result under all of its required cache keys.
-func (c *Cache[Value]) store(res result[Value]) {
+func (c *Cache[Value]) store(res result[Value]) (evict func()) {
// Get primary key
pnext := c.next
c.next++
@@ -341,7 +374,7 @@ func (c *Cache[Value]) store(res result[Value]) {
}
}
- // Drop these keys.
+ // Drop existing.
pkeys = pkeys[:0]
}
@@ -356,8 +389,10 @@ func (c *Cache[Value]) store(res result[Value]) {
Key: pnext,
Value: res,
}, func(_ int64, item *ttl.Entry[int64, result[Value]]) {
- c.cache.Evict(item)
+ evict = func() { c.cache.Evict(item.Key, item.Value) }
})
+
+ return evict
}
type result[Value any] struct {