Documentation
¶
Overview ¶
Package cascache implements a provider-agnostic cache with compare-and-swap (CAS) safety via per-key generations. Single-key reads never return stale values; bulk results are validated on read (per member) and rejected if any member is stale.
Components:
- Provider: byte store with TTL (e.g. Ristretto, BigCache, Redis).
- Codec[V]: (de)serializes V <-> []byte.
- GenStore: generation counter per logical key. Local (in-process) by default, optional Redis implementation for multi-replica / restart persistence.
Keys:
single:<ns>:<key> - single entries bulk:<ns>:<hash> - set-shaped entries (hash over sorted keys)
CAS pattern:
obs, err := cache.TrySnapshotGen(ctx, k) // before DB read
v := readFromDB(k)
if err == nil {
_ = cache.SetWithGen(ctx, k, v, obs, 0) // write iff current gen == obs
}
Index ¶
- Variables
- type BulkRejectReason
- type CAS
- type Cache
- type Hooks
- type InvalidateError
- type MissingObservedGensError
- type NopHooks
- func (NopHooks) BulkRejected(string, int, BulkRejectReason)
- func (NopHooks) GenBumpError(string, error)
- func (NopHooks) GenSnapshotError(int, error)
- func (NopHooks) InvalidateOutage(string, error, error)
- func (NopHooks) LocalGenWithBulk()
- func (NopHooks) ProviderSetRejected(string, bool)
- func (NopHooks) SelfHealSingle(string, SelfHealReason)
- type Options
- type SelfHealReason
- type SetCostFunc
Constants ¶
This section is empty.
Variables ¶
var ErrMissingObservedGens = errors.New("cascache: missing observed generations")
ErrMissingObservedGens identifies a SetBulkWithGens caller error where at least one item key has no corresponding observed generation.
Functions ¶
This section is empty.
Types ¶
type BulkRejectReason ¶ added in v0.3.1
type BulkRejectReason string
BulkRejectReason classifies why a bulk entry was rejected.
const ( // at least one bulk payload could not be decoded by the codec. BulkRejectReasonValueDecode BulkRejectReason = "value_decode" // bulk entry was missing members or contained stale generations. BulkRejectReasonInvalidOrStale BulkRejectReason = "invalid_or_stale" // bulk wire envelope was invalid. BulkRejectReasonDecodeError BulkRejectReason = "decode_error" // caller omitted at least one observed generation. BulkRejectReasonMissingObservedGen BulkRejectReason = "missing_observed_gen" // current generations could not be loaded. BulkRejectReasonGenSnapshotError BulkRejectReason = "gen_snapshot_error" // one observed generation no longer matched. BulkRejectReasonGenMismatch BulkRejectReason = "gen_mismatch" )
type CAS ¶
type CAS[V any] interface { Enabled() bool Close(context.Context) error // Single Get(ctx context.Context, key string) (v V, ok bool, err error) SetWithGen(ctx context.Context, key string, value V, observedGen uint64, ttl time.Duration) error Invalidate(ctx context.Context, key string) error // Bulk (order-agnostic return; use your own ordering by keys slice) GetBulk(ctx context.Context, keys []string) (values map[string]V, missing []string, err error) SetBulkWithGens(ctx context.Context, items map[string]V, observedGens map[string]uint64, ttl time.Duration) error // Error aware generation snapshots (for CAS). // TrySnapshotGens returns a generation for every unique logical key or an error. TrySnapshotGen(ctx context.Context, key string) (uint64, error) TrySnapshotGens(ctx context.Context, keys []string) (map[string]uint64, error) // Best effort generation snapshots. // Snapshot* report failures to Hooks and collapse failed snapshots to zero. SnapshotGen(ctx context.Context, key string) uint64 SnapshotGens(ctx context.Context, keys []string) map[string]uint64 }
CAS is the high-level, provider-agnostic cache API with CAS safety via per-key generations. V is the caller's value type. Serialization is handled by a pluggable Codec[V].
type Hooks ¶ added in v0.0.6
type Hooks interface {
SelfHealSingle(storageKey string, reason SelfHealReason)
BulkRejected(namespace string, requested int, reason BulkRejectReason)
ProviderSetRejected(storageKey string, isBulk bool)
GenSnapshotError(count int, err error)
GenBumpError(storageKey string, err error)
InvalidateOutage(key string, bumpErr, delErr error)
LocalGenWithBulk()
}
Hooks are lightweight callbacks for high-signal events. Implementations MUST be cheap and non-blocking; do not perform I/O. If work may block, buffer it and drop on backpressure (best effort).
func Multi ¶ added in v0.0.9
Multi returns a Hooks that fan-outs to all provided hooks, in order. Nil entries are ignored. Panics from a hook will propagate to the caller.
example usage:
logH := sloghook.New(slog.Default(), sloghook.Options{SelfHealEvery: 10}) metH := promhook.New(...) // some kind og metrics adapter auditH := myAuditHook{...} // audit adapter
// fan-out mh := cascache.MultiHooks{logH, metH, auditH}
// Either: single async queue for the whole fan-out hooks := asynchook.New(mh, 1, 1000)
// Or: give each hook its own queue (isolate backpressure)
hooks := cascache.MultiHooks{
asynchook.New(logH, 1, 1000),
asynchook.New(metH, 1, 1000),
asynchook.New(auditH, 1, 1000),
}
type InvalidateError ¶ added in v0.0.5
func (*InvalidateError) Error ¶ added in v0.0.5
func (e *InvalidateError) Error() string
func (*InvalidateError) Unwrap ¶ added in v0.0.5
func (e *InvalidateError) Unwrap() []error
type MissingObservedGensError ¶ added in v0.3.1
type MissingObservedGensError struct {
Missing []string
}
MissingObservedGensError reports which logical keys were missing observed generations.
func (*MissingObservedGensError) Error ¶ added in v0.3.1
func (e *MissingObservedGensError) Error() string
func (*MissingObservedGensError) Is ¶ added in v0.3.1
func (e *MissingObservedGensError) Is(target error) bool
type NopHooks ¶ added in v0.0.6
type NopHooks struct{}
NopHooks is a default no-op.
func (NopHooks) BulkRejected ¶ added in v0.0.6
func (NopHooks) BulkRejected(string, int, BulkRejectReason)
func (NopHooks) GenBumpError ¶ added in v0.0.6
func (NopHooks) GenSnapshotError ¶ added in v0.0.6
func (NopHooks) InvalidateOutage ¶ added in v0.0.6
func (NopHooks) LocalGenWithBulk ¶ added in v0.0.6
func (NopHooks) LocalGenWithBulk()
func (NopHooks) ProviderSetRejected ¶ added in v0.0.6
func (NopHooks) SelfHealSingle ¶ added in v0.0.6
func (NopHooks) SelfHealSingle(string, SelfHealReason)
type Options ¶
type Options[V any] struct { // Required Namespace string // logical namespace to avoid collisions. e.g. "user", "profile", "order" Provider pr.Provider Codec c.Codec[V] // Optional DefaultTTL time.Duration // singles; 0 => 10m BulkTTL time.Duration // bulks; 0 => 10m CleanupInterval time.Duration // 0 => 1h GenRetention time.Duration // 0 => 30d Disabled bool // default false (enabled) ComputeSetCost SetCostFunc // default 1 GenStore gen.GenStore // nil => LocalGenStore (in-process) DisableBulk bool // default false => bulk enabled Hooks Hooks // high-signal events for metrics/telemetry/logging }
Options tune the behavior of the generic CAS cache. Only Namespace and Provider are required; others have sensible defaults.
type SelfHealReason ¶ added in v0.3.1
type SelfHealReason string
SelfHealReason classifies why a single entry was deleted on read.
const ( // single-entry wire envelope was invalid. SelfHealReasonCorrupt SelfHealReason = "corrupt" // stored generation no longer matched the current generation. SelfHealReasonGenMismatch SelfHealReason = "gen_mismatch" // payload could not be decoded by the configured codec. SelfHealReasonValueDecode SelfHealReason = "value_decode" )
Directories
¶
| Path | Synopsis |
|---|---|
|
hooks
|
|
|
async
usage:
|
usage: |
|
slog
Package sloghook provides a slog-based implementation of cascache.Hooks.
|
Package sloghook provides a slog-based implementation of cascache.Hooks. |
|
internal
|
|
|
wire
Package wire contains the compact, versioned on-the-wire format used by cascache to store values in the underlying Provider.
|
Package wire contains the compact, versioned on-the-wire format used by cascache to store values in the underlying Provider. |
|
Package provider defines the storage abstraction used by cascache.
|
Package provider defines the storage abstraction used by cascache. |