fix(cache): invalidate derived scope keys on catalogue import

This commit is contained in:
MrAlders0n
2026-09-30 10:31:08 -04:00
committed by MrAlders0n
parent 3b548900a0
commit 9ce4e8d10c
3 changed files with 34 additions and 1 deletions
+18
View File
@@ -76,6 +76,24 @@ func (c *Client) del(ctx context.Context, keys ...string) {
c.rdb.Del(ctx, keys...)
}
// delPrefix SCANs the whole keyspace; call it rarely.
func (c *Client) delPrefix(ctx context.Context, prefix string) {
var cursor uint64
for {
keys, next, err := c.rdb.Scan(ctx, cursor, prefix+"*", 100).Result()
if err != nil {
return
}
if len(keys) > 0 {
c.rdb.Del(ctx, keys...)
}
if next == 0 {
return
}
cursor = next
}
}
// getOrSet retrieves a cached value by key, deserialising it into T.
// On a cache miss it calls fetch, stores the result under key with the given
// TTL, and returns it. If Redis is unavailable or returns an unexpected error,
+13
View File
@@ -383,6 +383,19 @@ func TestCachedReader_IATASortingForStableKey(t *testing.T) {
}
}
func TestInvalidateScopeNamesClearsDerivedKeys(t *testing.T) {
c, mr := newTestClient(t)
cr := &CachedReader{inner: &stubReader{}, c: c, ttl: CacheTTLs{}}
for _, k := range []string{keyScopeNames, keyScopesByIATAsPrefix + "YOW", keyScopesByIATAsPrefix + "YOW,YVR", keyScopeByNamePrefix + "#yow"} {
mr.Set(k, "x")
}
mr.Set("beacon:iatas", "keep")
cr.InvalidateScopeNames(context.Background())
if got := mr.Keys(); len(got) != 1 || got[0] != "beacon:iatas" {
t.Fatalf("keys left: %v", got)
}
}
func TestCachedReader_InvalidateNode(t *testing.T) {
c, mr := newTestClient(t)
nodeID := uuid.MustParse("00000000-0000-0000-0000-000000000001")
+3 -1
View File
@@ -80,9 +80,11 @@ func NewCachedReader(inner api.Reader, c *Client, ttl CacheTTLs) api.Reader {
}
}
// InvalidateScopeNames makes newly committed catalogue names available to filters.
// InvalidateScopeNames makes newly committed catalogue names visible to every scope read.
func (cr *CachedReader) InvalidateScopeNames(ctx context.Context) {
cr.c.del(ctx, keyScopeNames)
cr.c.delPrefix(ctx, keyScopesByIATAsPrefix)
cr.c.delPrefix(ctx, keyScopeByNamePrefix)
}
// InvalidateNode removes the cached entries for a node by UUID.