cache

package
v0.48.0 Latest Latest
Warning

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

Go to latest
Published: Sep 10, 2026 License: Apache-2.0 Imports: 7 Imported by: 0

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

View Source
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.

onEvict runs off the cache lock

The user onEvict may perform slow teardown (e.g. closing network connections). To keep that work off the shared cache lock, the LRU's own eviction callback only *buffers* each evicted entry (bufferEvicted); every mutating operation then drains the buffer and invokes the user onEvict via drainEvictions after releasing mu. onEvict therefore never runs while mu is held, so a slow onEvict never blocks Get/Set/RemoveMatching on other keys.

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. It is always invoked outside the cache lock (see the type doc), so it is safe for onEvict to perform slow teardown without blocking other cache operations.

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]) RemoveMatching added in v0.48.0

func (c *ValidatingCache[K, V]) RemoveMatching(pred func(K, V) bool) int

RemoveMatching evicts every entry for which pred reports true, invoking the user onEvict for each removed entry, and returns the number removed.

pred runs under the cache lock (the same lock Set contends for) and must not call back into the cache. onEvict, however, runs via drainEvictions after all removals complete and the lock is released, so a slow onEvict (e.g. closing a hung backend connection) delays only the drain, never the shared cache lock: a concurrent Set/Get on any key proceeds while a slow teardown is in flight. This is intended for infrequent bulk eviction (e.g. reconciling sessions after a backend is removed from the registry), not a hot path.

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 — after mu is released, so a slow onEvict does not block concurrent cache operations.

Jump to

Keyboard shortcuts

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