Documentation
¶
Overview ¶
Package cache is a pluggable key-value cache with required TTL on every write. The interface is byte-oriented so it stays driver-agnostic; typed access goes through the generic Get / Set / GetOrSet helpers, which JSON-encode/decode values.
TTL is non-optional on purpose — caches without expiry silently grow into a memory leak in long-running services. Every write must pick a deadline. Use a long Duration if you really want "rarely expires".
Backends ¶
- MemoryCache — process-local, default for tests and single-pod dev.
- cache/postgrescache — sqlx-style table-backed cache (opt-in import).
- cache/rediscache — Redis-backed cache via go-redis (opt-in import).
Example ¶
c := cache.NewMemory() _ = cache.Set(ctx, c, "user:123", &user, 60*time.Second) u, _, _ := cache.Get[User](ctx, c, "user:123")
Index ¶
- Variables
- func EnsurePositiveTTL(ttl time.Duration) error
- func Get[T any](ctx context.Context, c Cache, key string) (T, bool, error)
- func GetOrSet[T any](ctx context.Context, c Cache, key string, ttl time.Duration, ...) (T, error)
- func Set[T any](ctx context.Context, c Cache, key string, value T, ttl time.Duration) error
- type Cache
- type DeserializeError
- type MemoryCache
- func (c *MemoryCache) Delete(_ context.Context, key string) error
- func (c *MemoryCache) GetBytes(_ context.Context, key string) ([]byte, bool, error)
- func (c *MemoryCache) ReapExpired(_ context.Context)
- func (c *MemoryCache) SetBytes(_ context.Context, key string, value []byte, ttl time.Duration) error
- type SerializeError
Constants ¶
This section is empty.
Variables ¶
var ( // ErrInvalidTTL — TTL was zero or negative. ErrInvalidTTL = errors.New("cache: TTL must be greater than zero") // ErrBackend — backend-level I/O failure (network, query, etc.). // Wrap with fmt.Errorf("...: %w", ErrBackend) for context. ErrBackend = errors.New("cache: backend error") )
Sentinel errors. Use errors.Is to branch.
Functions ¶
func EnsurePositiveTTL ¶
EnsurePositiveTTL is the standard guard at the trait boundary so every backend returns the same error shape.
func Get ¶
Get reads key and JSON-decodes into T. Returns (zero, false, nil) on a miss / expired entry. Returns *DeserializeError if the stored bytes don't decode into T.
func GetOrSet ¶
func GetOrSet[T any]( ctx context.Context, c Cache, key string, ttl time.Duration, supplier func(ctx context.Context) (T, error), ) (T, error)
GetOrSet returns the cached value if present; otherwise calls supplier, caches the result with ttl, and returns it.
Not atomic across replicas: two callers racing on the same key may both invoke supplier (the loser's write overwrites the winner's). If you need exactly-once supplier execution, layer a lock.LockProvider around the call.
Types ¶
type Cache ¶
type Cache interface {
// GetBytes reads the raw bytes for key. Returns (nil, false, nil) for a
// miss OR for an entry whose TTL has elapsed (expired entries are
// treated as missing regardless of whether the backend has cleaned
// them up yet).
GetBytes(ctx context.Context, key string) ([]byte, bool, error)
// SetBytes writes value for key, expiring after ttl. Overwrites any
// existing value. Implementations must reject zero / negative TTLs
// by returning ErrInvalidTTL.
SetBytes(ctx context.Context, key string, value []byte, ttl time.Duration) error
// Delete removes key. Returns nil whether or not the key existed.
Delete(ctx context.Context, key string) error
}
Cache is the pluggable contract. Implementations store opaque bytes; typed access is provided by the Get / Set / GetOrSet free helpers.
TTL is required on every write — a cache entry without an expiry is almost always a bug in long-running services. If you genuinely want near-permanent storage, pass a very long Duration.
type DeserializeError ¶
type DeserializeError struct{ Cause error }
DeserializeError signals a JSON → Go failure on a Get / GetOrSet call.
func (*DeserializeError) Error ¶
func (e *DeserializeError) Error() string
func (*DeserializeError) Unwrap ¶
func (e *DeserializeError) Unwrap() error
type MemoryCache ¶
type MemoryCache struct {
// contains filtered or unexported fields
}
MemoryCache is a process-local cache for tests and single-pod deployments. Expired entries are reaped lazily on read — no background sweeper, so memory cost is bounded by the number of distinct keys ever written (until each is read again or ReapExpired is called).
func (*MemoryCache) Delete ¶
func (c *MemoryCache) Delete(_ context.Context, key string) error
Delete removes key. Idempotent — returns nil whether or not it existed.
func (*MemoryCache) ReapExpired ¶
func (c *MemoryCache) ReapExpired(_ context.Context)
ReapExpired walks the map and drops entries whose TTL has elapsed. The lazy reap on read covers the common case; call this from a periodic task if you write keys that are rarely read back.
type SerializeError ¶
type SerializeError struct{ Cause error }
SerializeError signals a Go → JSON failure on a Set / GetOrSet call.
func (*SerializeError) Error ¶
func (e *SerializeError) Error() string
func (*SerializeError) Unwrap ¶
func (e *SerializeError) Unwrap() error
Directories
¶
| Path | Synopsis |
|---|---|
|
Package postgrescache is a pgx-backed cache that satisfies cache.Cache.
|
Package postgrescache is a pgx-backed cache that satisfies cache.Cache. |
|
Package rediscache is a Redis-backed cache that satisfies cache.Cache.
|
Package rediscache is a Redis-backed cache that satisfies cache.Cache. |