cache

package
v0.0.11 Latest Latest
Warning

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

Go to latest
Published: Nov 1, 2026 License: Apache-2.0 Imports: 5 Imported by: 0

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

Constants

This section is empty.

Variables

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

func EnsurePositiveTTL(ttl time.Duration) error

EnsurePositiveTTL is the standard guard at the trait boundary so every backend returns the same error shape.

func Get

func Get[T any](ctx context.Context, c Cache, key string) (T, bool, error)

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.

func Set

func Set[T any](ctx context.Context, c Cache, key string, value T, ttl time.Duration) error

Set JSON-encodes value and writes it with the given TTL.

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 NewMemory

func NewMemory() *MemoryCache

NewMemory builds an empty MemoryCache.

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) GetBytes

func (c *MemoryCache) GetBytes(_ context.Context, key string) ([]byte, bool, error)

GetBytes returns the value if present and not expired.

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.

func (*MemoryCache) SetBytes

func (c *MemoryCache) SetBytes(_ context.Context, key string, value []byte, ttl time.Duration) error

SetBytes inserts or replaces key with the given TTL.

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.

Jump to

Keyboard shortcuts

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