diff options
author | 2023-05-09 15:17:43 +0100 | |
---|---|---|
committer | 2023-05-09 16:17:43 +0200 | |
commit | 8275d70e38579128f0680ee4001a944907a3772a (patch) | |
tree | ce97c3f6609bcbc6d24c7423ef7c0247011e2122 /vendor/codeberg.org/gruf/go-cache | |
parent | [chore] tidy + update StatusToAPIStatus (#1754) (diff) | |
download | gotosocial-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.go | 97 | ||||
-rw-r--r-- | vendor/codeberg.org/gruf/go-cache/v3/result/key.go | 12 |
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 } |