summaryrefslogtreecommitdiff
path: root/vendor/codeberg.org/gruf/go-cache
diff options
context:
space:
mode:
authorLibravatar kim <89579420+NyaaaWhatsUpDoc@users.noreply.github.com>2023-05-09 15:17:43 +0100
committerLibravatar GitHub <noreply@github.com>2023-05-09 16:17:43 +0200
commit8275d70e38579128f0680ee4001a944907a3772a (patch)
treece97c3f6609bcbc6d24c7423ef7c0247011e2122 /vendor/codeberg.org/gruf/go-cache
parent[chore] tidy + update StatusToAPIStatus (#1754) (diff)
downloadgotosocial-8275d70e38579128f0680ee4001a944907a3772a.tar.xz
[bugfix] update go-cache version to support multi-keying (#1756)
* update go-cache version to support multi-keying Signed-off-by: kim <grufwub@gmail.com> * improved cache invalidation Signed-off-by: kim <grufwub@gmail.com> --------- Signed-off-by: kim <grufwub@gmail.com>
Diffstat (limited to 'vendor/codeberg.org/gruf/go-cache')
-rw-r--r--vendor/codeberg.org/gruf/go-cache/v3/result/cache.go97
-rw-r--r--vendor/codeberg.org/gruf/go-cache/v3/result/key.go12
2 files changed, 62 insertions, 47 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 12b86d8bb..805a4d989 100644
--- a/vendor/codeberg.org/gruf/go-cache/v3/result/cache.go
+++ b/vendor/codeberg.org/gruf/go-cache/v3/result/cache.go
@@ -19,6 +19,10 @@ type Lookup struct {
// under zero value keys, otherwise ignore them.
AllowZero bool
+ // Multi allows specifying a key capable of storing
+ // multiple results. Note this only supports invalidate.
+ Multi bool
+
// TODO: support toggling case sensitive lookups.
// CaseSensitive bool
}
@@ -155,10 +159,14 @@ func (c *Cache[Value]) Load(lookup string, load func() (Value, error), keyParts
var (
zero Value
res result[Value]
+ ok bool
)
// Get lookup key info by name.
keyInfo := c.lookups.get(lookup)
+ if !keyInfo.unique {
+ panic("non-unique lookup does not support load: " + lookup)
+ }
// Generate cache key string.
ckey := keyInfo.genKey(keyParts)
@@ -167,11 +175,11 @@ func (c *Cache[Value]) Load(lookup string, load func() (Value, error), keyParts
c.cache.Lock()
// Look for primary cache key
- pkey, ok := keyInfo.pkeys[ckey]
+ pkeys := keyInfo.pkeys[ckey]
- if ok {
+ if ok = (len(pkeys) > 0); ok {
// Fetch the result for primary key
- entry, _ := c.cache.Cache.Get(pkey)
+ entry, _ := c.cache.Cache.Get(pkeys[0])
res = entry.Value
}
@@ -252,9 +260,13 @@ func (c *Cache[Value]) Store(value Value, store func() error) error {
// Has checks the cache for a positive result under the given lookup and key parts.
func (c *Cache[Value]) Has(lookup string, keyParts ...any) bool {
var res result[Value]
+ var ok bool
// Get lookup key info by name.
keyInfo := c.lookups.get(lookup)
+ if !keyInfo.unique {
+ panic("non-unique lookup does not support has: " + lookup)
+ }
// Generate cache key string.
ckey := keyInfo.genKey(keyParts)
@@ -263,11 +275,11 @@ func (c *Cache[Value]) Has(lookup string, keyParts ...any) bool {
c.cache.Lock()
// Look for primary key for cache key
- pkey, ok := keyInfo.pkeys[ckey]
+ pkeys := keyInfo.pkeys[ckey]
- if ok {
+ if ok = (len(pkeys) > 0); ok {
// Fetch the result for primary key
- entry, _ := c.cache.Cache.Get(pkey)
+ entry, _ := c.cache.Cache.Get(pkeys[0])
res = entry.Value
}
@@ -288,63 +300,60 @@ func (c *Cache[Value]) Invalidate(lookup string, keyParts ...any) {
// Look for primary key for cache key
c.cache.Lock()
- pkey, ok := keyInfo.pkeys[ckey]
+ pkeys := keyInfo.pkeys[ckey]
c.cache.Unlock()
- if !ok {
- return
+ for _, pkey := range pkeys {
+ // Invalidate each primary key
+ c.cache.Invalidate(pkey)
}
-
- // Invalid by primary key
- c.cache.Invalidate(pkey)
}
// Clear empties the cache, calling the invalidate callback.
-func (c *Cache[Value]) Clear() {
- c.cache.Clear()
-}
+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]) {
- for _, key := range res.Keys {
- pkeys := key.info.pkeys
-
- // Look for cache primary key
- pkey, ok := pkeys[key.key]
-
- if ok {
- // Get the overlapping result with this key.
- entry, _ := c.cache.Cache.Get(pkey)
-
- // From conflicting entry, drop this key, this
- // will prevent eviction cleanup key confusion.
- entry.Value.Keys.drop(key.info.name)
-
- if len(entry.Value.Keys) == 0 {
- // We just over-wrote the only lookup key for
- // this value, so we drop its primary key too.
- c.cache.Cache.Delete(pkey)
- }
- }
- }
-
// Get primary key
- pkey := c.next
+ pnext := c.next
c.next++
- if pkey > c.next {
+ if pnext > c.next {
panic("cache primary key overflow")
}
- // Store all primary key lookups
for _, key := range res.Keys {
- pkeys := key.info.pkeys
- pkeys[key.key] = pkey
+ // Look for cache primary keys.
+ pkeys := key.info.pkeys[key.key]
+
+ if key.info.unique && len(pkeys) > 0 {
+ for _, conflict := range pkeys {
+ // Get the overlapping result with this key.
+ entry, _ := c.cache.Cache.Get(conflict)
+
+ // From conflicting entry, drop this key, this
+ // will prevent eviction cleanup key confusion.
+ entry.Value.Keys.drop(key.info.name)
+
+ if len(entry.Value.Keys) == 0 {
+ // We just over-wrote the only lookup key for
+ // this value, so we drop its primary key too.
+ c.cache.Cache.Delete(conflict)
+ }
+ }
+
+ // Drop these keys.
+ pkeys = pkeys[:0]
+ }
+
+ // Store primary key lookup.
+ pkeys = append(pkeys, pnext)
+ key.info.pkeys[key.key] = pkeys
}
// Store main entry under primary key, using evict hook if needed
- c.cache.Cache.SetWithHook(pkey, &ttl.Entry[int64, result[Value]]{
+ c.cache.Cache.SetWithHook(pnext, &ttl.Entry[int64, result[Value]]{
Expiry: time.Now().Add(c.cache.TTL),
- Key: pkey,
+ Key: pnext,
Value: res,
}, func(_ int64, item *ttl.Entry[int64, result[Value]]) {
c.cache.Evict(item)
diff --git a/vendor/codeberg.org/gruf/go-cache/v3/result/key.go b/vendor/codeberg.org/gruf/go-cache/v3/result/key.go
index 6be316c2b..bcf12c3de 100644
--- a/vendor/codeberg.org/gruf/go-cache/v3/result/key.go
+++ b/vendor/codeberg.org/gruf/go-cache/v3/result/key.go
@@ -122,14 +122,17 @@ type structKey struct {
// zero != "" --> don't allow zero value keys
zero string
+ // unique determines whether this structKey supports
+ // multiple or just the singular unique result.
+ unique bool
+
// fields is a slice of runtime struct field
// indices, of the fields encompassed by this key.
-
fields []structField
// pkeys is a lookup of stored struct key values
// to the primary cache lookup key (int64).
- pkeys map[string]int64
+ pkeys map[string][]int64
}
type structField struct {
@@ -220,8 +223,11 @@ func newStructKey(lk Lookup, t reflect.Type) structKey {
sk.zero = sk.genKey(zeros)
}
+ // Set unique lookup flag.
+ sk.unique = !lk.Multi
+
// Allocate primary lookup map
- sk.pkeys = make(map[string]int64)
+ sk.pkeys = make(map[string][]int64)
return sk
}