Documentation
¶
Overview ¶
Package cache is fabriq's caching adapter: the core/cache port implemented over grove kv's Store (redis driver). It is the place grove kv "earns its keep" per docs/decisions/0003-redis-client.md. Generation counters use the raw redis client (INCR) via grove's documented Unwrap escape hatch.
Index ¶
- func RunL1EvictTailer(ctx context.Context, t eventTailer, l *L1Cache) error
- type Adapter
- func (a *Adapter) Close() error
- func (a *Adapter) Get(ctx context.Context, ks corecache.Keyspace, key string) (val []byte, ok bool, err error)
- func (a *Adapter) GetOrLoad(ctx context.Context, ks corecache.Keyspace, key string, ...) ([]byte, error)
- func (a *Adapter) Invalidate(ctx context.Context, ks corecache.Keyspace, keys ...string) error
- func (a *Adapter) InvalidateEntity(ctx context.Context, entity string) error
- func (a *Adapter) InvalidateKeyspace(ctx context.Context, ks corecache.Keyspace) error
- func (a *Adapter) Set(ctx context.Context, ks corecache.Keyspace, key string, val []byte) error
- type Config
- type L1Cache
- func (l *L1Cache) Close() error
- func (l *L1Cache) EvictLocal(ctx context.Context, entity string, ids ...string)
- func (l *L1Cache) Get(ctx context.Context, ks corecache.Keyspace, key string) (val []byte, ok bool, err error)
- func (l *L1Cache) GetOrLoad(ctx context.Context, ks corecache.Keyspace, key string, ...) ([]byte, error)
- func (l *L1Cache) Invalidate(ctx context.Context, ks corecache.Keyspace, keys ...string) error
- func (l *L1Cache) InvalidateEntity(ctx context.Context, entity string) error
- func (l *L1Cache) InvalidateKeyspace(ctx context.Context, ks corecache.Keyspace) error
- func (l *L1Cache) Set(ctx context.Context, ks corecache.Keyspace, key string, val []byte) error
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func RunL1EvictTailer ¶
RunL1EvictTailer drives per-node L1 eviction from the event stream: every committed change evicts this node's L1 for the changed entity + id. Blocks until ctx ends. It is best-effort — a handler error on one envelope is skipped (best-effort; no logger wired — the L1 TTL backstops a missed eviction) and tailing continues.
Types ¶
type Adapter ¶
type Adapter struct {
// contains filtered or unexported fields
}
Adapter implements core/cache.Cache over a grove kv Store.
func (*Adapter) Get ¶
func (a *Adapter) Get(ctx context.Context, ks corecache.Keyspace, key string) (val []byte, ok bool, err error)
Get returns the cached value; ok=false on miss.
func (*Adapter) GetOrLoad ¶
func (a *Adapter) GetOrLoad(ctx context.Context, ks corecache.Keyspace, key string, load func(context.Context) ([]byte, error)) ([]byte, error)
GetOrLoad returns the cached value for key, or calls load exactly once (single-flight per key) on a miss, stores the result and returns it.
func (*Adapter) Invalidate ¶
Invalidate removes specific keys from the keyspace (targeted eviction).
func (*Adapter) InvalidateEntity ¶
InvalidateEntity bumps the entity generation (INCR) for Global + Tenant + (if a scope is present) TenantScope partitions. A failure on any partition returns the first error; partial bumps are safe (over-invalidation only).
func (*Adapter) InvalidateKeyspace ¶
InvalidateKeyspace bumps the keyspace generation, orphaning every entry under it in the current partition at once (no mass deletes).
type L1Cache ¶
type L1Cache struct {
// contains filtered or unexported fields
}
L1Cache is a per-node in-process cache in front of an inner cache.Cache (the shared Redis L2). It implements cache.Cache so it is transparent to all consumers. Query-keyspace entries are kept coherent via a LOCAL generation map (no per-access L2 read); row-keyspace entries evict per-id (preserving the P3a sibling-warmth invariant). The writing node clears its own L1 through the normal Invalidate*/Set path; other nodes via EvictLocal (driven by the broadcast event tailer).
func (*L1Cache) EvictLocal ¶
EvictLocal clears this node's L1 for a committed change to (entity, ids) observed via the event stream. It is LOCAL-ONLY (never touches the inner L2 — the writing node already did). It orphans the entity's query entries (local gen bump) and deletes the per-id row entries.
func (*L1Cache) Get ¶
func (l *L1Cache) Get(ctx context.Context, ks corecache.Keyspace, key string) (val []byte, ok bool, err error)
Get returns the cached value from L1 on a hit; on an L1 miss it falls through to the inner L2. When the inner returns a hit the value is populated into L1 (write-on-read) so subsequent Gets are served locally. This preserves the cache hierarchy: a cold L1 (fresh node, after eviction, or after restart) still benefits from the shared L2 rather than forcing a DB reload on every Get.
func (*L1Cache) GetOrLoad ¶
func (l *L1Cache) GetOrLoad(ctx context.Context, ks corecache.Keyspace, key string, load func(context.Context) ([]byte, error)) ([]byte, error)
GetOrLoad returns the cached value for key, or calls load exactly once on a miss, stores the result, and returns it.
func (*L1Cache) Invalidate ¶
Invalidate removes specific keys from the keyspace (targeted per-id eviction). Delegates to inner and removes the matching L1 entries.
func (*L1Cache) InvalidateEntity ¶
InvalidateEntity bumps the entity generation in inner (L2) and locally, so every query keyspace (Entity == entity) is orphaned in L1 across all partitions. Row keyspaces (no Entity) are NOT bumped here; they evict per-id.
func (*L1Cache) InvalidateKeyspace ¶
InvalidateKeyspace bumps the keyspace generation in inner and orphans the corresponding local generation so all L1 entries for this keyspace+partition are abandoned without mass deletion.