Documentation
¶
Overview ¶
Package cache provides a generic, capacity-bounded cache with singleflight deduplication and per-hit liveness validation.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrExpired = errors.New("cache entry expired")
ErrExpired is returned by the check function passed to New to signal that a cached entry has definitively expired and should be evicted.
Functions ¶
This section is empty.
Types ¶
type ValidatingCache ¶
type ValidatingCache[K comparable, V any] struct { // contains filtered or unexported fields }
ValidatingCache is a node-local write-through cache backed by a capacity-bounded LRU map, with singleflight-deduplicated Get operations and lazy liveness validation on cache hit.
Type parameter K is the key type (must be comparable). Type parameter V is the cached value type.
The entire Get operation — cache hit validation and miss load — runs under a singleflight group so at most one operation executes concurrently per key. Concurrent callers for the same key share the result, coalescing both liveness checks and storage round-trips into a single operation per key.
func New ¶
func New[K comparable, V any]( capacity int, load func(context.Context, K) (V, error), check func(context.Context, K, V) error, onEvict func(K, V), ) *ValidatingCache[K, V]
New creates a ValidatingCache with the given capacity and callbacks.
capacity is the maximum number of entries; it must be >= 1. When the cache is full and a new entry must be stored, the least-recently-used entry is evicted first. Values less than 1 panic.
load is called on a cache miss to restore the value; it must not be nil. check is called on every cache hit to confirm liveness. It receives both the key and the cached value so callers can inspect the value without a separate read. Returning ErrExpired evicts the entry; any other error is transient (cached value returned unchanged). It must not be nil. onEvict is called after any eviction (LRU or expiry); it may be nil.
func (*ValidatingCache[K, V]) Get ¶
func (c *ValidatingCache[K, V]) Get(ctx context.Context, key K) (V, bool)
Get returns the value for key, loading it on a cache miss. The entire operation — cache hit validation and miss load — runs under a singleflight group so at most one operation executes concurrently per key. Concurrent callers for the same key share the result.
ctx is forwarded to the load and check callbacks. When concurrent calls for the same key are coalesced by singleflight, only the first caller's context is forwarded; later callers' contexts are not used.
On a cache hit the entry's liveness is validated via the check function provided to New: ErrExpired evicts the entry and falls through to load; transient errors return the cached value unchanged. On a cache miss, load is called to restore the value.
The returned bool is false whenever the value is unavailable — either because load returned an error or because the key does not exist in the backing store. Callers cannot distinguish these two cases.
func (*ValidatingCache[K, V]) Len ¶
func (c *ValidatingCache[K, V]) Len() int
Len returns the number of entries currently in the cache.
func (*ValidatingCache[K, V]) Set ¶
func (c *ValidatingCache[K, V]) Set(key K, value V)
Set stores value under key, moving the entry to the MRU position. If the cache is at capacity, the least-recently-used entry is evicted first and onEvict is called for it.