cache

package
v0.19.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 5, 2026 License: MIT Imports: 11 Imported by: 0

README

cache (service)

Concrete cache stores implementing internal/core/data/cache (ADR 0049): a tagged, stampede-protected memory store over the kernel LRU+TTL primitive, and the chain that puts one store in front of another.

store, err := cache.NewMemory[Profile](cache.MemoryConfig{
    MaxEntries: 10_000,        // refused if zero — a capacity is the caller's decision
    DefaultTTL: time.Minute,
})

loader, _ := store.(corecache.Loader[Profile])
p, err := loader.Load(ctx, key, fill)   // one fill per key, per process

tagger, _ := store.(corecache.Tagger)
removed, err := tagger.InvalidateTag(ctx, "user:42")

Invalidation is O(k) in the entries carrying the tag, not O(N) in the store — measured at two store sizes in BENCH.md.

Stampede protection collapses concurrent misses within one process; it does not coordinate across replicas.

Public facade: pkg/v1/data/cache. See CLAUDE.md for the lock discipline, the four removal paths, and the chain's ordering rules.

Documentation

Overview

Package cache — hosts the compile-time interface assertions, keeping them out of the production source so the runtime binary carries no diagnostic-only declarations.

Package cache — the L1/L2 chain.

Package cache — the NewChain constructor configuration.

Package cache provides the concrete cache stores implementing internal/core/data/cache: a tagged, stampede-protected memory store over the kernel LRU+TTL primitive, and the chain that puts one store in front of another. Stdlib-only, cross-OS. ADR 0049.

Package cache — the tagged, stampede-protected in-memory store.

Package cache — what the underlying primitive actually stores.

Package cache — the refusals every store shares, and the wrapping rule for a caller's fill error.

Package cache — the two-way tag index behind InvalidateTag.

Package cache — one level of a chained store.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewChain

func NewChain[V any](cfg ChainConfig, stores ...corecache.Store[V]) (chain corecache.Store[V], err error)

NewChain puts each store in front of the next: tiers[0] is the nearest and is consulted first, the last is the authority.

Every tier MUST implement corecache.EntryFetcher and corecache.Tagger. That is checked here, once, and refused with corecache.CacheChainMisconfigured rather than discovered per call — see that sentinel for the reasoning.

The returned value is a corecache.Store and also implements corecache.EntryFetcher, corecache.Tagger and corecache.Loader.

IFACE-PLUGIN: the concrete chain stays unexported behind this constructor.

func NewMemory

func NewMemory[V any](cfg MemoryConfig) (store corecache.Store[V], err error)

NewMemory builds an in-process cache store from cfg.

The returned value is a corecache.Store. It also implements corecache.EntryFetcher, corecache.Tagger and corecache.Loader; reach them by type assertion, which is the ADR 0039 way a port grows without breaking anyone who implemented it.

A non-positive MaxEntries is REFUSED, not defaulted. ADR 0031 splits on whether the SDK can supply a value without inventing the caller's requirement, and a cache capacity is the requirement: it is the whole statement of how much memory the caller is willing to spend. Worse, the value the primitive gives a zero — unbounded — is the dangerous reading, and it is dangerous twice over here, because an unbounded store also grows an unbounded tag index.

IFACE-PLUGIN: the concrete store stays unexported behind this constructor.

Types

type ChainConfig

type ChainConfig struct {
	// OnPromoteError, if non-nil, is called when a value served from a FAR
	// tier could not be written into a nearer one.
	//
	// A failed promotion is not a failed read: the caller already has the
	// value, and failing the call would turn a degraded cache into a degraded
	// service. But it is also not nothing — a near tier that rejects every
	// promotion is a tier that will never be used again, and with this hook nil
	// that is completely invisible. Wire it.
	OnPromoteError func(key string, err error)
}

ChainConfig parameterises NewChain. Its zero value builds a working chain; the one field is an observation hook, not a policy.

type MemoryConfig

type MemoryConfig struct {
	// MaxEntries caps the live entry count; the least-recently-used entry is
	// evicted above it. It MUST be positive.
	MaxEntries int
	// DefaultTTL applies to every entry whose own TTL is zero. Zero means the
	// default is "no deadline", so entries leave only by eviction, by Delete,
	// or by tag invalidation. Negative is refused.
	DefaultTTL time.Duration
	// Clock is the time source, injectable so TTL is testable. nil means
	// clock.System. Only the reading half of the port is used — a cache reads
	// time, it never waits for it (ADR 0039).
	Clock clock.Clock
}

MemoryConfig parameterises NewMemory.

Its zero value is deliberately NOT a working cache: MaxEntries must be stated. See NewMemory for why that refusal, and not a default, is the right ADR 0031 half here.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL