Documentation
¶
Overview ¶
Package refcache implements a generic refcount-pinned LRU cache for expensive credential-keyed resources (DB pools, Redis clients).
Two design properties matter:
Refcount-pinned entries: Get() returns the resource plus a release closure. The entry's refcount is held above zero until release runs, so concurrent eviction cannot close a resource another goroutine is using.
Singleflight on the slow path: when N goroutines miss the fast path for the same key, only ONE factory call runs (the leader's). The other N-1 wait for it to complete, then bump the refcount on the leader's inserted entry. This eliminates wasted parallel TLS handshakes / pool creations under contention, which is especially important for pgx and Redis where each connection costs 50-200ms of network I/O.
db.PoolCache and cache.ClientCache are thin wrappers around this package — they add credential validation, key derivation, and resource construction, then delegate the lifecycle management here.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Cache ¶
type Cache[T any] struct { // contains filtered or unexported fields }
Cache is a refcount-pinned LRU cache of T values keyed by string. T is typically a pointer type (e.g., *pgxpool.Pool, *cache.Client).
func New ¶
New creates a Cache. closer is called on every value that needs disposal (LRU eviction, factory's limit-error fallback, Close). label is prefixed onto error messages so callers can attribute pool-limit errors to a specific domain.
func (*Cache[T]) Close ¶
func (c *Cache[T]) Close()
Close disposes of every cached value via the closer.
func (*Cache[T]) Get ¶
Get returns the value for key plus a release closure. If the key is not cached, factory is called to create it. The returned value is refcount-pinned until release runs — concurrent eviction cannot dispose of it. Pair every Get with a deferred release call.
Concurrent Gets for the same missing key coalesce via singleflight: only one factory call runs, all callers receive the same value, and each caller's refcount is bumped exactly once.