refcache

package
v0.4.20 Latest Latest
Warning

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

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

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

func New[T any](maxSize int, label string, closer func(T)) *Cache[T]

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

func (c *Cache[T]) Get(key string, factory func() (T, error)) (T, func(), error)

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.

Jump to

Keyboard shortcuts

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