Documentation
¶
Overview ¶
Package gencache provides a generation-stamped memo cache: a value cache whose entries are invalidated wholesale when a monotonic "generation" counter advances.
Unlike an LRU, there is no per-entry TTL and no eviction order. Every entry carries the generation it was computed under; a read is a hit only if that stamp still matches the current generation. Any change to the underlying data bumps the generation, which invalidates every entry at once without touching the map.
It fits when: the value is a pure function of some shared state, that state changes rarely relative to reads, and a single monotonic counter can stand in for "the state changed" (e.g. a sum of write counters across the stores the value is derived from).
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Cache ¶
type Cache[V any] struct { // contains filtered or unexported fields }
Cache is a concurrent generation-stamped memo. The zero value is not usable; construct one with New.
func New ¶
New builds a Cache. gen supplies the current generation (see GenFunc). maxEntries bounds the map: when inserting a new key would exceed it, the whole map is flushed first, because cache keys are often client-controlled and an unbounded map is a memory-growth vector. A maxEntries <= 0 means unbounded.
func (*Cache[V]) Get ¶
Get returns the cached value for key when it is present and still current (honoring WithClone). The bool reports whether it was a live hit; a stale or missing entry returns the zero value and false.
func (*Cache[V]) GetOrCompute ¶
GetOrCompute returns the current cached value for key, or computes it with compute, stores it, and returns it.
The stored entry is stamped with the generation read BEFORE compute ran: if the underlying data changes while compute is in flight, the entry is left stale and the next call recomputes — the cache never serves a stale read. Honors WithClone on the returned value and WithSkipStore (a skipped result is returned but not cached). compute may run concurrently for the same key under load; it must be safe to call redundantly and its results must be equivalent.
type GenFunc ¶
type GenFunc func() uint64
GenFunc returns the current generation. It must strictly increase (never repeat a prior value) whenever the data the cache derives from changes; any increase invalidates every cached entry. It is called on every Get/GetOrCompute, so keep it cheap — typically a sum of atomic counters.
type Option ¶
Option configures a Cache.
func WithClone ¶
WithClone makes Get and GetOrCompute return clone(v) rather than the stored value, so callers cannot mutate cached state through the value they receive. Use it for mutable values such as slices or maps (e.g. a wrapper around slices.Clone). Default: the stored value is returned as-is, which is correct only when V is treated as immutable.
func WithSkipStore ¶
WithSkipStore leaves results matching skip out of the cache: they are still returned, but recomputed on the next call. Use it to avoid caching "not found" answers, e.g. func(v []T) bool { return len(v) == 0 }. Default: every result is stored.