cache

package module
v0.0.0-...-c7aa06f Latest Latest
Warning

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

Go to latest
Published: Feb 21, 2026 License: MIT Imports: 35 Imported by: 0

README

cache logo

cache gives your services one cache API with multiple backend options. Swap drivers without refactoring.

Go Reference Go version Latest tag Go Report Card Tests

What cache is

An explicit cache abstraction with a minimal Store interface and ergonomic Cache helpers. Drivers are chosen when you construct the store, so swapping backends is a dependency-injection change instead of a refactor.

Drivers

Driver / Backend Mode Shared Durable TTL Counters Notes
Null No-op - - - - Great for tests: cache calls are no-ops and never persist.
File Local filesystem - Simple durability on a single host; point WithFileDir to writable disk.
Memory In-process - - Fastest; per-process only, best for single-node or short-lived data.
Memcached Networked - Millisecond access; TTL resolution is 1s; use multiple nodes via WithMemcachedAddresses.
Redis Networked - Full feature set; supports prefixing and counters with per-key TTL refresh.
NATS Networked - JetStream KeyValue-backed driver; inject an existing bucket via WithNATSKeyValue.
DynamoDB Networked Backed by DynamoDB (supports localstack/dynamodb-local).
SQL Networked / local Postgres / MySQL / SQLite via database/sql; table schema managed automatically.

Installation

go get github.com/goforj/cache

Quick Start

import (
    "context"
    "time"

    "github.com/goforj/cache"
    "github.com/redis/go-redis/v9"
)

func main() {
    ctx := context.Background()

    store := cache.NewMemoryStore(ctx, cache.WithDefaultTTL(5*time.Minute))
    c := cache.NewCache(store)

    // Remember pattern.
    type Profile struct { Name string `json:"name"` }

    profile, err := cache.Remember[Profile](c, "user:42:profile", time.Minute, func() (Profile, error) {
        return Profile{Name: "Ada"}, nil
    })
    fmt.Println(profile.Name) // Ada

    // Switch to Redis (dependency injection, no code changes below).
    client := redis.NewClient(&redis.Options{Addr: "127.0.0.1:6379"})
    store = cache.NewRedisStore(ctx, client, cache.WithPrefix("app"), cache.WithDefaultTTL(5*time.Minute))
    c = cache.NewCache(store)
}

StoreConfig

StoreConfig keeps configuration explicit:

  • Driver: explicit backend (null, file, memory, memcached, redis, nats, dynamodb, sql)
  • DefaultTTL: fallback TTL when a call provides ttl <= 0
  • MemoryCleanupInterval: sweep interval for memory driver
  • Prefix: key prefix for shared backends
  • RedisClient / NATSKeyValue / MemcachedAddresses / DynamoClient / SQLDriverName+DSN: driver-specific inputs
  • Compression / MaxValueBytes / EncryptionKey: shaping and security controls

Behavior Semantics

For precise runtime semantics, see Behavior Semantics:

  • TTL/default-TTL matrix by operation/helper
  • stale and refresh-ahead behavior and edge cases
  • lock and rate-limit guarantees (process-local vs distributed scope)

Production Guidance

For deployment defaults and operational patterns, see Production Guide:

  • recommended defaults and tuning
  • key naming/versioning conventions
  • TTL jitter and miss-storm mitigation
  • observability instrumentation patterns

Memoized reads

Wrap any store with NewMemoStore to memoize reads within the process; cache is invalidated automatically on write paths.

memoStore := cache.NewMemoStore(store)
memoRepo := cache.NewCache(memoStore)

Staleness note: memoization is per-process only. Writes that happen in other processes (or outside your app) will not invalidate this memo cache. Use it when local staleness is acceptable, or scope it narrowly (e.g., per-request) if multiple writers exist.

Testing

Unit tests cover the public helpers. Integration tests use testcontainers-go to spin up Redis:

go test -tags=integration ./...

Use INTEGRATION_DRIVER=redis (comma-separated; defaults to all) to select which drivers start containers and run the contract suite.

Benchmarks

go test ./docs/bench -tags benchrender

Note: NATS numbers can look slower than Redis/memory because the NATS driver preserves per-operation TTL semantics by storing per-key expiry metadata (envelope encode/decode) and may do extra compare/update steps for some operations.

Note: DynamoDB is intentionally omitted from these local charts because emulator-based numbers are not representative of real AWS latency.

NATS variants in these charts:

  • nats: per-key TTL semantics using a binary envelope (magic/expiresAt/value). This preserves per-key expiry parity with other drivers, with modest metadata overhead.
  • nats_bucket_ttl: bucket-level TTL mode (WithNATSBucketTTL(true)), raw value path; faster but different expiry semantics.

Latency (ns/op)

Cache benchmark latency chart

Iterations (N)

Cache benchmark iteration chart

Allocated Bytes (B/op)

Cache benchmark bytes chart

Allocations (allocs/op)

Cache benchmark allocs chart

Testing helpers

For unit tests that shouldn’t hit real infrastructure, use the in-memory fake with call assertions:

f := cachefake.New()
c := f.Cache()

// exercise code under test
_ = c.SetString("settings:mode", "dark", 0)
_, _, _ = c.Get("settings:mode")
_ = c.Delete("settings:mode")

f.AssertCalled(t, cachefake.OpSet, "settings:mode", 1)
f.AssertCalled(t, cachefake.OpGet, "settings:mode", 1)
f.AssertCalled(t, cachefake.OpDelete, "settings:mode", 1)
f.AssertNotCalled(t, cachefake.OpAdd, "settings:mode")

API reference

The API section below is autogenerated; do not edit between the markers.

API Index

Group Functions
Constructors NewDynamoStore NewFileStore NewMemcachedStore NewMemoryStore NewNATSStore NewNullStore NewRedisStore NewSQLStore NewStore NewStoreWith
Core Driver NewCache NewCacheWithTTL Store
Invalidation Delete DeleteCtx DeleteMany DeleteManyCtx Flush FlushCtx Pull PullCtx
Locking Lock LockCtx TryLock TryLockCtx Unlock UnlockCtx
Memoization NewMemoStore
Observability WithObserver
Options WithCompression WithDefaultTTL WithDynamoClient WithDynamoEndpoint WithDynamoRegion WithDynamoTable WithEncryptionKey WithFileDir WithMaxValueBytes WithMemcachedAddresses WithMemoryCleanupInterval WithNATSBucketTTL WithNATSKeyValue WithPrefix WithRedisClient WithSQL
Rate Limiting RateLimit RateLimitCtx RateLimitWithRemaining RateLimitWithRemainingCtx
Read Through Remember RememberBytes RememberCtx RememberJSON RememberJSONCtx RememberStale RememberStaleBytes RememberStaleBytesCtx RememberStaleCtx RememberStaleValueWithCodec RememberString RememberStringCtx RememberValue RememberValueWithCodec
Reads BatchGet BatchGetCtx Get GetCtx GetJSON GetJSONCtx GetString GetStringCtx
Refresh Ahead RefreshAhead RefreshAheadCtx RefreshAheadValueWithCodec
Writes Add AddCtx BatchSet BatchSetCtx Decrement DecrementCtx Increment IncrementCtx Set SetCtx SetJSON SetJSONCtx SetString SetStringCtx

Constructors

NewDynamoStore

NewDynamoStore is a convenience for a DynamoDB-backed store.

ctx := context.Background()
store := cache.NewDynamoStore(ctx, cache.StoreConfig{DynamoEndpoint: "http://localhost:8000"})
fmt.Println(store.Driver()) // dynamodb

NewFileStore

NewFileStore is a convenience for a filesystem-backed store.

ctx := context.Background()
store := cache.NewFileStore(ctx, "/tmp/my-cache")
fmt.Println(store.Driver()) // file

NewMemcachedStore

NewMemcachedStore is a convenience for a memcached-backed store.

ctx := context.Background()
store := cache.NewMemcachedStore(ctx, []string{"127.0.0.1:11211"})
fmt.Println(store.Driver()) // memcached

NewMemoryStore

NewMemoryStore is a convenience for an in-process store with optional overrides.

ctx := context.Background()
store := cache.NewMemoryStore(ctx)
fmt.Println(store.Driver()) // memory

NewNATSStore

NewNATSStore is a convenience for a NATS JetStream KeyValue-backed store.

ctx := context.Background()
var kv cache.NATSKeyValue // provided by your NATS setup
store := cache.NewNATSStore(ctx, kv, cache.WithPrefix("app"))
fmt.Println(store.Driver()) // nats

NewNullStore

NewNullStore is a no-op store useful for tests where caching should be disabled.

ctx := context.Background()
store := cache.NewNullStore(ctx)
fmt.Println(store.Driver()) // null

NewRedisStore

NewRedisStore is a convenience for a redis-backed store. Redis client is required.

ctx := context.Background()
redisClient := redis.NewClient(&redis.Options{Addr: "127.0.0.1:6379"})
store := cache.NewRedisStore(ctx, redisClient, cache.WithPrefix("app"))
fmt.Println(store.Driver()) // redis

NewSQLStore

NewSQLStore builds a SQL-backed store (postgres, mysql, sqlite).

Example: sqlite helper

ctx := context.Background()
store := cache.NewSQLStore(ctx, "sqlite", "file:cache.db?cache=shared&mode=rwc", "cache_entries")
fmt.Println(store.Driver()) // sql

Example: postgres helper

dsnPg := "postgres://user:pass@localhost:5432/app?sslmode=disable"
storePg := cache.NewSQLStore(ctx, "pgx", dsnPg, "cache_entries")
fmt.Println(storePg.Driver()) // sql

Example: mysql helper

dsnMy := "user:pass@tcp(localhost:3306)/app?parseTime=true"
storeMy := cache.NewSQLStore(ctx, "mysql", dsnMy, "cache_entries")
fmt.Println(storeMy.Driver()) // sql

NewStore

NewStore returns a concrete store for the requested driver. Caller is responsible for providing any driver-specific dependencies.

ctx := context.Background()
store := cache.NewStore(ctx, cache.StoreConfig{
	Driver: cache.DriverMemory,
})
fmt.Println(store.Driver()) // memory

NewStoreWith

NewStoreWith builds a store using a driver and a set of functional options. Required data (e.g., Redis client) must be provided via options when needed.

Example: memory store (options)

ctx := context.Background()
store := cache.NewStoreWith(ctx, cache.DriverMemory)
fmt.Println(store.Driver()) // memory

Example: redis store (options)

redisClient := redis.NewClient(&redis.Options{Addr: "127.0.0.1:6379"})
store = cache.NewStoreWith(ctx, cache.DriverRedis,
	cache.WithRedisClient(redisClient),
	cache.WithPrefix("app"),
	cache.WithDefaultTTL(5*time.Minute),
)
fmt.Println(store.Driver()) // redis

Core

Driver

Driver reports the underlying store driver.

NewCache

NewCache creates a cache facade bound to a concrete store.

ctx := context.Background()
s := cache.NewMemoryStore(ctx)
c := cache.NewCache(s)
fmt.Println(c.Driver()) // memory

NewCacheWithTTL

NewCacheWithTTL lets callers override the default TTL applied when ttl <= 0.

ctx := context.Background()
s := cache.NewMemoryStore(ctx)
c := cache.NewCacheWithTTL(s, 2*time.Minute)
fmt.Println(c.Driver(), c != nil) // memory true

Store

Store returns the underlying store implementation.

ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
fmt.Println(c.Store().Driver()) // memory

Invalidation

Delete

Delete removes a single key.

ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
fmt.Println(c.Delete("a") == nil) // true

DeleteCtx

DeleteCtx is the context-aware variant of Delete.

DeleteMany

DeleteMany removes multiple keys.

ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
fmt.Println(c.DeleteMany("a", "b") == nil) // true

DeleteManyCtx

DeleteManyCtx is the context-aware variant of DeleteMany.

Flush

Flush clears all keys for this store scope.

ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
fmt.Println(c.Flush() == nil) // true

FlushCtx

FlushCtx is the context-aware variant of Flush.

Pull

Pull returns value and removes it from cache.

ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
body, ok, _ := c.Pull("reset:token:42")
fmt.Println(ok, string(body)) // true abc

PullCtx

PullCtx is the context-aware variant of Pull.

Locking

Lock

Lock waits until the lock is acquired or timeout elapses.

ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
locked, err := c.Lock("job:sync", 10*time.Second, time.Second)
fmt.Println(err == nil, locked) // true true

LockCtx

LockCtx retries lock acquisition until success or context cancellation.

TryLock

TryLock acquires a short-lived lock key when not already held.

ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
locked, _ := c.TryLock("job:sync", 10*time.Second)
fmt.Println(locked) // true

TryLockCtx

TryLockCtx is the context-aware variant of TryLock.

Unlock

Unlock releases a previously acquired lock key.

ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
locked, _ := c.TryLock("job:sync", 10*time.Second)
if locked {
}

UnlockCtx

UnlockCtx is the context-aware variant of Unlock.

Memoization

NewMemoStore

NewMemoStore decorates store with per-process read memoization.

Behavior:

  • First Get hits the backing store, clones the value, and memoizes it in-process.
  • Subsequent Get for the same key returns the memoized clone (no backend call).
  • Any write/delete/flush invalidates the memo entry so local reads stay in sync with changes made through this process.
  • Memo data is per-process only; other processes or external writers will not invalidate it. Use only when that staleness window is acceptable.
ctx := context.Background()
base := cache.NewMemoryStore(ctx)
memo := cache.NewMemoStore(base)
c := cache.NewCache(memo)
fmt.Println(c.Driver()) // memory

Observability

WithObserver

WithObserver attaches an observer to receive operation events.

Options

WithCompression

WithCompression enables value compression using the chosen codec.

ctx := context.Background()
store := cache.NewStoreWith(ctx, cache.DriverMemory, cache.WithCompression(cache.CompressionGzip))
fmt.Println(store.Driver()) // memory

WithDefaultTTL

WithDefaultTTL overrides the fallback TTL used when ttl <= 0.

ctx := context.Background()
store := cache.NewStoreWith(ctx, cache.DriverMemory, cache.WithDefaultTTL(30*time.Second))
fmt.Println(store.Driver()) // memory

WithDynamoClient

WithDynamoClient injects a pre-built DynamoDB client.

ctx := context.Background()
var client cache.DynamoAPI // assume already configured
store := cache.NewStoreWith(ctx, cache.DriverDynamo, cache.WithDynamoClient(client))
fmt.Println(store.Driver()) // dynamodb

WithDynamoEndpoint

WithDynamoEndpoint sets the DynamoDB endpoint (useful for local testing).

ctx := context.Background()
store := cache.NewStoreWith(ctx, cache.DriverDynamo, cache.WithDynamoEndpoint("http://localhost:8000"))
fmt.Println(store.Driver()) // dynamodb

WithDynamoRegion

WithDynamoRegion sets the DynamoDB region for requests.

ctx := context.Background()
store := cache.NewStoreWith(ctx, cache.DriverDynamo, cache.WithDynamoRegion("us-west-2"))
fmt.Println(store.Driver()) // dynamodb

WithDynamoTable

WithDynamoTable sets the table used by the DynamoDB driver.

ctx := context.Background()
store := cache.NewStoreWith(ctx, cache.DriverDynamo, cache.WithDynamoTable("cache_entries"))
fmt.Println(store.Driver()) // dynamodb

WithEncryptionKey

WithEncryptionKey enables at-rest encryption using the provided AES key (16/24/32 bytes).

ctx := context.Background()
key := []byte("01234567890123456789012345678901")
store := cache.NewStoreWith(ctx, cache.DriverFile, cache.WithEncryptionKey(key))
fmt.Println(store.Driver()) // file

WithFileDir

WithFileDir sets the directory used by the file driver.

ctx := context.Background()
store := cache.NewStoreWith(ctx, cache.DriverFile, cache.WithFileDir("/tmp/cache"))
fmt.Println(store.Driver()) // file

WithMaxValueBytes

WithMaxValueBytes sets a per-entry size limit (0 disables the check).

ctx := context.Background()
store := cache.NewStoreWith(ctx, cache.DriverMemory, cache.WithMaxValueBytes(1024))
fmt.Println(store.Driver()) // memory

WithMemcachedAddresses

WithMemcachedAddresses sets memcached server addresses (host:port).

ctx := context.Background()
store := cache.NewStoreWith(ctx, cache.DriverMemcached, cache.WithMemcachedAddresses("127.0.0.1:11211"))
fmt.Println(store.Driver()) // memcached

WithMemoryCleanupInterval

WithMemoryCleanupInterval overrides the sweep interval for the memory driver.

ctx := context.Background()
store := cache.NewStoreWith(ctx, cache.DriverMemory, cache.WithMemoryCleanupInterval(5*time.Minute))
fmt.Println(store.Driver()) // memory

WithNATSBucketTTL

WithNATSBucketTTL toggles bucket-level TTL mode for DriverNATS. When enabled, values are stored as raw bytes and per-operation ttl values are ignored.

ctx := context.Background()
var kv cache.NATSKeyValue // provided by your NATS setup
store := cache.NewStoreWith(ctx, cache.DriverNATS,
	cache.WithNATSKeyValue(kv),
	cache.WithNATSBucketTTL(true),
)
fmt.Println(store.Driver()) // nats

WithNATSKeyValue

WithNATSKeyValue sets the NATS JetStream KeyValue bucket; required when using DriverNATS.

ctx := context.Background()
var kv cache.NATSKeyValue // provided by your NATS setup
store := cache.NewStoreWith(ctx, cache.DriverNATS, cache.WithNATSKeyValue(kv))
fmt.Println(store.Driver()) // nats

WithPrefix

WithPrefix sets the key prefix for shared backends (e.g., redis).

ctx := context.Background()
store := cache.NewStoreWith(ctx, cache.DriverRedis, cache.WithPrefix("svc"))
fmt.Println(store.Driver()) // redis

WithRedisClient

WithRedisClient sets the redis client; required when using DriverRedis.

ctx := context.Background()
rdb := redis.NewClient(&redis.Options{Addr: "127.0.0.1:6379"})
store := cache.NewStoreWith(ctx, cache.DriverRedis, cache.WithRedisClient(rdb))
fmt.Println(store.Driver()) // redis

WithSQL

WithSQL configures the SQL driver (driver name + DSN + optional table).

ctx := context.Background()
store := cache.NewStoreWith(ctx, cache.DriverSQL,
	cache.WithSQL("sqlite", "file::memory:?cache=shared", "cache_entries"),
	cache.WithPrefix("svc"),
)
fmt.Println(store.Driver()) // sql

Rate Limiting

RateLimit

RateLimit increments key in a fixed window and reports whether requests are allowed.

ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
allowed, count, _ := c.RateLimit("rl:login:user:42", 5, time.Minute)
fmt.Println(allowed, count >= 1) // true true

RateLimitCtx

RateLimitCtx is the context-aware variant of RateLimit.

RateLimitWithRemaining

RateLimitWithRemaining increments a fixed-window counter and returns allowance metadata.

ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
allowed, count, remaining, resetAt, err := c.RateLimitWithRemaining("rl:api:ip:1.2.3.4", 100, time.Minute)
fmt.Println(err == nil, allowed, count >= 1, remaining >= 0, resetAt.After(time.Now()))

RateLimitWithRemainingCtx

RateLimitWithRemainingCtx is the context-aware variant of RateLimitWithRemaining.

Read Through

Remember

Remember is the ergonomic, typed remember helper using JSON encoding by default.

type Profile struct { Name string `json:"name"` }
ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
profile, err := cache.Remember[Profile](c, "profile:42", time.Minute, func() (Profile, error) {
	return Profile{Name: "Ada"}, nil
})
fmt.Println(err == nil, profile.Name) // true Ada

RememberBytes

RememberBytes returns key value or computes/stores it when missing.

ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
data, err := c.RememberBytes("dashboard:summary", time.Minute, func() ([]byte, error) {
	return []byte("payload"), nil
})
fmt.Println(err == nil, string(data)) // true payload

RememberCtx

RememberCtx is the context-aware variant of RememberBytes.

RememberJSON

RememberJSON returns key value or computes/stores JSON when missing.

type Settings struct { Enabled bool `json:"enabled"` }
ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
settings, err := cache.RememberJSON[Settings](c, "settings:alerts", time.Minute, func() (Settings, error) {
	return Settings{Enabled: true}, nil
})
fmt.Println(err == nil, settings.Enabled) // true true

RememberJSONCtx

RememberJSONCtx is the context-aware variant of RememberJSON.

RememberStale

RememberStale returns a typed value with stale fallback semantics using JSON encoding by default.

type Profile struct { Name string `json:"name"` }
ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
profile, usedStale, err := cache.RememberStale[Profile](c, "profile:42", time.Minute, 10*time.Minute, func() (Profile, error) {
	return Profile{Name: "Ada"}, nil
})
fmt.Println(err == nil, usedStale, profile.Name) // true false Ada

RememberStaleBytes

RememberStaleBytes returns a fresh value when available, otherwise computes and caches it. If computing fails and a stale value exists, it returns the stale value. The returned bool is true when a stale fallback was used.

ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
body, usedStale, err := c.RememberStaleBytes("profile:42", time.Minute, 10*time.Minute, func() ([]byte, error) {
	return []byte(`{"name":"Ada"}`), nil
})
fmt.Println(err == nil, usedStale, len(body) > 0)

RememberStaleBytesCtx

RememberStaleBytesCtx is the context-aware variant of RememberStaleBytes.

RememberStaleCtx

RememberStaleCtx returns a typed value with stale fallback semantics using JSON encoding by default.

type Profile struct { Name string `json:"name"` }
ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
profile, usedStale, err := cache.RememberStaleCtx[Profile](ctx, c, "profile:42", time.Minute, 10*time.Minute, func(ctx context.Context) (Profile, error) {
	return Profile{Name: "Ada"}, nil
})
fmt.Println(err == nil, usedStale, profile.Name) // true false Ada

RememberStaleValueWithCodec

RememberStaleValueWithCodec allows custom encoding/decoding for typed stale remember operations.

type Profile struct { Name string }
codec := cache.ValueCodec[Profile]{
	Encode: func(v Profile) ([]byte, error) { return []byte(v.Name), nil },
	Decode: func(b []byte) (Profile, error) { return Profile{Name: string(b)}, nil },
}
ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
profile, usedStale, err := cache.RememberStaleValueWithCodec(ctx, c, "profile:42", time.Minute, 10*time.Minute, func() (Profile, error) {
	return Profile{Name: "Ada"}, nil
}, codec)
fmt.Println(err == nil, usedStale, profile.Name) // true false Ada

RememberString

RememberString returns key value or computes/stores it when missing.

ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
val, err := c.RememberString("settings:mode", time.Minute, func() (string, error) {
	return "on", nil
})
fmt.Println(err == nil, val) // true on

RememberStringCtx

RememberStringCtx is the context-aware variant of RememberString.

RememberValue

RememberValue returns a typed value or computes/stores it when missing using JSON encoding by default.

type Summary struct { Text string `json:"text"` }
ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
s, err := cache.RememberValue[Summary](c, "dashboard:summary", time.Minute, func() (Summary, error) {
	return Summary{Text: "ok"}, nil
})
fmt.Println(err == nil, s.Text) // true ok

RememberValueWithCodec

RememberValueWithCodec allows custom encoding/decoding for typed remember operations.

Reads

BatchGet

BatchGet returns all found values for the provided keys. Missing keys are omitted from the returned map.

ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
values, err := c.BatchGet("a", "b", "missing")
fmt.Println(err == nil, string(values["a"]), string(values["b"])) // true 1 2

BatchGetCtx

BatchGetCtx is the context-aware variant of BatchGet.

Get

Get returns raw bytes for key when present.

ctx := context.Background()
s := cache.NewMemoryStore(ctx)
c := cache.NewCache(s)
value, ok, _ := c.Get("user:42")
fmt.Println(ok, string(value)) // true Ada

GetCtx

GetCtx is the context-aware variant of Get.

GetJSON

GetJSON decodes a JSON value into T when key exists, using background context.

type Profile struct { Name string `json:"name"` }
ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
profile, ok, err := cache.GetJSON[Profile](c, "profile:42")
fmt.Println(err == nil, ok, profile.Name) // true true Ada

GetJSONCtx

GetJSONCtx is the context-aware variant of GetJSON.

GetString

GetString returns a UTF-8 string value for key when present.

ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
name, ok, _ := c.GetString("user:42:name")
fmt.Println(ok, name) // true Ada

GetStringCtx

GetStringCtx is the context-aware variant of GetString.

Refresh Ahead

RefreshAhead

RefreshAhead returns cached value immediately and refreshes asynchronously when near expiry. On miss, it computes and stores synchronously.

Example: refresh ahead

ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
body, err := c.RefreshAhead("dashboard:summary", time.Minute, 10*time.Second, func() ([]byte, error) {
	return []byte("payload"), nil
})
fmt.Println(err == nil, len(body) > 0) // true true

Example: refresh ahead typed

type Summary struct { Text string `json:"text"` }
ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
s, err := cache.RefreshAhead[Summary](c, "dashboard:summary", time.Minute, 10*time.Second, func() (Summary, error) {
	return Summary{Text: "ok"}, nil
})
fmt.Println(err == nil, s.Text) // true ok

RefreshAheadCtx

RefreshAheadCtx is the context-aware variant of RefreshAhead.

RefreshAheadValueWithCodec

RefreshAheadValueWithCodec allows custom encoding/decoding for typed refresh-ahead operations.

Writes

Add

Add writes value only when key is not already present.

ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
created, _ := c.Add("boot:seeded", []byte("1"), time.Hour)
fmt.Println(created) // true

AddCtx

AddCtx is the context-aware variant of Add.

BatchSet

BatchSet writes many key/value pairs using a shared ttl.

ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
err := c.BatchSet(map[string][]byte{
	"a": []byte("1"),
	"b": []byte("2"),
}, time.Minute)
fmt.Println(err == nil) // true

BatchSetCtx

BatchSetCtx is the context-aware variant of BatchSet.

Decrement

Decrement decrements a numeric value and returns the result.

ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
val, _ := c.Decrement("rate:login:42", 1, time.Minute)
fmt.Println(val) // -1

DecrementCtx

DecrementCtx is the context-aware variant of Decrement.

Increment

Increment increments a numeric value and returns the result.

ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
val, _ := c.Increment("rate:login:42", 1, time.Minute)
fmt.Println(val) // 1

IncrementCtx

IncrementCtx is the context-aware variant of Increment.

Set

Set writes raw bytes to key.

ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
fmt.Println(c.Set("token", []byte("abc"), time.Minute) == nil) // true

SetCtx

SetCtx is the context-aware variant of Set.

SetJSON

SetJSON encodes value as JSON and writes it to key using background context.

type Settings struct { Enabled bool `json:"enabled"` }
ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
err := cache.SetJSON(c, "settings:alerts", Settings{Enabled: true}, time.Minute)
fmt.Println(err == nil) // true

SetJSONCtx

SetJSONCtx is the context-aware variant of SetJSON.

SetString

SetString writes a string value to key.

ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
fmt.Println(c.SetString("user:42:name", "Ada", time.Minute) == nil) // true

SetStringCtx

SetStringCtx is the context-aware variant of SetString.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrValueTooLarge      = errors.New("cache: value exceeds max size")
	ErrUnsupportedCodec   = errors.New("cache: unsupported compression codec")
	ErrCorruptCompression = errors.New("cache: corrupt compressed payload")
)
View Source
var (
	ErrEncryptionKey      = errors.New("cache: encryption key must be 16, 24, or 32 bytes")
	ErrDecryptFailed      = errors.New("cache: decrypt failed")
	ErrEncryptValueTooBig = errors.New("cache: encrypt value too large")
)

Functions

func GetJSON

func GetJSON[T any](cache *Cache, key string) (T, bool, error)

GetJSON decodes a JSON value into T when key exists, using background context. @group Reads

Example: get typed JSON

type Profile struct { Name string `json:"name"` }
ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
_ = cache.SetJSON(c, "profile:42", Profile{Name: "Ada"}, time.Minute)
profile, ok, err := cache.GetJSON[Profile](c, "profile:42")
fmt.Println(err == nil, ok, profile.Name) // true true Ada

func GetJSONCtx

func GetJSONCtx[T any](ctx context.Context, cache *Cache, key string) (T, bool, error)

GetJSONCtx is the context-aware variant of GetJSON. @group Reads

func RefreshAhead

func RefreshAhead[T any](cache *Cache, key string, ttl, refreshAhead time.Duration, fn func() (T, error)) (T, error)

RefreshAhead returns a typed value and refreshes asynchronously when near expiry. @group Refresh Ahead

Example: refresh ahead typed

type Summary struct { Text string `json:"text"` }
ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
s, err := cache.RefreshAhead[Summary](c, "dashboard:summary", time.Minute, 10*time.Second, func() (Summary, error) {
	return Summary{Text: "ok"}, nil
})
fmt.Println(err == nil, s.Text) // true ok

func RefreshAheadCtx

func RefreshAheadCtx[T any](ctx context.Context, cache *Cache, key string, ttl, refreshAhead time.Duration, fn func(context.Context) (T, error)) (T, error)

RefreshAheadCtx is the context-aware variant of RefreshAhead. @group Refresh Ahead

func RefreshAheadValueWithCodec

func RefreshAheadValueWithCodec[T any](ctx context.Context, cache *Cache, key string, ttl, refreshAhead time.Duration, fn func() (T, error), codec ValueCodec[T]) (T, error)

RefreshAheadValueWithCodec allows custom encoding/decoding for typed refresh-ahead operations. @group Refresh Ahead

func Remember

func Remember[T any](cache *Cache, key string, ttl time.Duration, fn func() (T, error)) (T, error)

Remember is the ergonomic, typed remember helper using JSON encoding by default. @group Read Through

Example: remember typed value

type Profile struct { Name string `json:"name"` }
ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
profile, err := cache.Remember[Profile](c, "profile:42", time.Minute, func() (Profile, error) {
	return Profile{Name: "Ada"}, nil
})
fmt.Println(err == nil, profile.Name) // true Ada

func RememberJSON

func RememberJSON[T any](cache *Cache, key string, ttl time.Duration, fn func() (T, error)) (T, error)

RememberJSON returns key value or computes/stores JSON when missing. @group Read Through

Example: remember JSON

type Settings struct { Enabled bool `json:"enabled"` }
ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
settings, err := cache.RememberJSON[Settings](c, "settings:alerts", time.Minute, func() (Settings, error) {
	return Settings{Enabled: true}, nil
})
fmt.Println(err == nil, settings.Enabled) // true true

func RememberJSONCtx

func RememberJSONCtx[T any](ctx context.Context, cache *Cache, key string, ttl time.Duration, fn func(context.Context) (T, error)) (T, error)

RememberJSONCtx is the context-aware variant of RememberJSON. @group Read Through

func RememberStale

func RememberStale[T any](cache *Cache, key string, ttl, staleTTL time.Duration, fn func() (T, error)) (T, bool, error)

RememberStale returns a typed value with stale fallback semantics using JSON encoding by default. @group Read Through

Example: remember stale typed

type Profile struct { Name string `json:"name"` }
ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
profile, usedStale, err := cache.RememberStale[Profile](c, "profile:42", time.Minute, 10*time.Minute, func() (Profile, error) {
	return Profile{Name: "Ada"}, nil
})
fmt.Println(err == nil, usedStale, profile.Name) // true false Ada

func RememberStaleCtx

func RememberStaleCtx[T any](ctx context.Context, cache *Cache, key string, ttl, staleTTL time.Duration, fn func(context.Context) (T, error)) (T, bool, error)

RememberStaleCtx returns a typed value with stale fallback semantics using JSON encoding by default. @group Read Through

Example: remember stale typed with context

type Profile struct { Name string `json:"name"` }
ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
profile, usedStale, err := cache.RememberStaleCtx[Profile](ctx, c, "profile:42", time.Minute, 10*time.Minute, func(ctx context.Context) (Profile, error) {
	return Profile{Name: "Ada"}, nil
})
fmt.Println(err == nil, usedStale, profile.Name) // true false Ada

func RememberStaleValueWithCodec

func RememberStaleValueWithCodec[T any](ctx context.Context, cache *Cache, key string, ttl, staleTTL time.Duration, fn func() (T, error), codec ValueCodec[T]) (T, bool, error)

RememberStaleValueWithCodec allows custom encoding/decoding for typed stale remember operations. @group Read Through

Example: remember stale with custom codec

type Profile struct { Name string }
codec := cache.ValueCodec[Profile]{
	Encode: func(v Profile) ([]byte, error) { return []byte(v.Name), nil },
	Decode: func(b []byte) (Profile, error) { return Profile{Name: string(b)}, nil },
}
ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
profile, usedStale, err := cache.RememberStaleValueWithCodec(ctx, c, "profile:42", time.Minute, 10*time.Minute, func() (Profile, error) {
	return Profile{Name: "Ada"}, nil
}, codec)
fmt.Println(err == nil, usedStale, profile.Name) // true false Ada

func RememberValue

func RememberValue[T any](cache *Cache, key string, ttl time.Duration, fn func() (T, error)) (T, error)

RememberValue returns a typed value or computes/stores it when missing using JSON encoding by default. @group Read Through

Example: remember typed value (codec default)

type Summary struct { Text string `json:"text"` }
ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
s, err := cache.RememberValue[Summary](c, "dashboard:summary", time.Minute, func() (Summary, error) {
	return Summary{Text: "ok"}, nil
})
fmt.Println(err == nil, s.Text) // true ok

func RememberValueWithCodec

func RememberValueWithCodec[T any](ctx context.Context, cache *Cache, key string, ttl time.Duration, fn func() (T, error), codec ValueCodec[T]) (T, error)

RememberValueWithCodec allows custom encoding/decoding for typed remember operations. @group Read Through

func SetJSON

func SetJSON[T any](cache *Cache, key string, value T, ttl time.Duration) error

SetJSON encodes value as JSON and writes it to key using background context. @group Writes

Example: set typed JSON

type Settings struct { Enabled bool `json:"enabled"` }
ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
err := cache.SetJSON(c, "settings:alerts", Settings{Enabled: true}, time.Minute)
fmt.Println(err == nil) // true

func SetJSONCtx

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

SetJSONCtx is the context-aware variant of SetJSON. @group Writes

Types

type Cache

type Cache struct {
	// contains filtered or unexported fields
}

Cache provides an ergonomic cache API on top of Store.

func NewCache

func NewCache(store Store) *Cache

NewCache creates a cache facade bound to a concrete store. @group Core

Example: cache from store

ctx := context.Background()
s := cache.NewMemoryStore(ctx)
c := cache.NewCache(s)
fmt.Println(c.Driver()) // memory

func NewCacheWithTTL

func NewCacheWithTTL(store Store, defaultTTL time.Duration) *Cache

NewCacheWithTTL lets callers override the default TTL applied when ttl <= 0. @group Core

Example: cache with custom default TTL

ctx := context.Background()
s := cache.NewMemoryStore(ctx)
c := cache.NewCacheWithTTL(s, 2*time.Minute)
fmt.Println(c.Driver(), c != nil) // memory true

func (*Cache) Add

func (c *Cache) Add(key string, value []byte, ttl time.Duration) (bool, error)

Add writes value only when key is not already present. @group Writes

Example: add once

ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
created, _ := c.Add("boot:seeded", []byte("1"), time.Hour)
fmt.Println(created) // true

func (*Cache) AddCtx

func (c *Cache) AddCtx(ctx context.Context, key string, value []byte, ttl time.Duration) (bool, error)

AddCtx is the context-aware variant of Add. @group Writes

func (*Cache) BatchGet

func (c *Cache) BatchGet(keys ...string) (map[string][]byte, error)

BatchGet returns all found values for the provided keys. Missing keys are omitted from the returned map. @group Reads

Example: batch get keys

ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
_ = c.Set("a", []byte("1"), time.Minute)
_ = c.Set("b", []byte("2"), time.Minute)
values, err := c.BatchGet("a", "b", "missing")
fmt.Println(err == nil, string(values["a"]), string(values["b"])) // true 1 2

func (*Cache) BatchGetCtx

func (c *Cache) BatchGetCtx(ctx context.Context, keys ...string) (map[string][]byte, error)

BatchGetCtx is the context-aware variant of BatchGet. @group Reads

func (*Cache) BatchSet

func (c *Cache) BatchSet(values map[string][]byte, ttl time.Duration) error

BatchSet writes many key/value pairs using a shared ttl. @group Writes

Example: batch set keys

ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
err := c.BatchSet(map[string][]byte{
	"a": []byte("1"),
	"b": []byte("2"),
}, time.Minute)
fmt.Println(err == nil) // true

func (*Cache) BatchSetCtx

func (c *Cache) BatchSetCtx(ctx context.Context, values map[string][]byte, ttl time.Duration) error

BatchSetCtx is the context-aware variant of BatchSet. @group Writes

func (*Cache) Decrement

func (c *Cache) Decrement(key string, delta int64, ttl time.Duration) (int64, error)

Decrement decrements a numeric value and returns the result. @group Writes

Example: decrement counter

ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
val, _ := c.Decrement("rate:login:42", 1, time.Minute)
fmt.Println(val) // -1

func (*Cache) DecrementCtx

func (c *Cache) DecrementCtx(ctx context.Context, key string, delta int64, ttl time.Duration) (int64, error)

DecrementCtx is the context-aware variant of Decrement. @group Writes

func (*Cache) Delete

func (c *Cache) Delete(key string) error

Delete removes a single key. @group Invalidation

Example: delete key

ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
_ = c.Set("a", []byte("1"), time.Minute)
fmt.Println(c.Delete("a") == nil) // true

func (*Cache) DeleteCtx

func (c *Cache) DeleteCtx(ctx context.Context, key string) error

DeleteCtx is the context-aware variant of Delete. @group Invalidation

func (*Cache) DeleteMany

func (c *Cache) DeleteMany(keys ...string) error

DeleteMany removes multiple keys. @group Invalidation

Example: delete many keys

ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
fmt.Println(c.DeleteMany("a", "b") == nil) // true

func (*Cache) DeleteManyCtx

func (c *Cache) DeleteManyCtx(ctx context.Context, keys ...string) error

DeleteManyCtx is the context-aware variant of DeleteMany. @group Invalidation

func (*Cache) Driver

func (c *Cache) Driver() Driver

Driver reports the underlying store driver. @group Core

func (*Cache) Flush

func (c *Cache) Flush() error

Flush clears all keys for this store scope. @group Invalidation

Example: flush all keys

ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
_ = c.Set("a", []byte("1"), time.Minute)
fmt.Println(c.Flush() == nil) // true

func (*Cache) FlushCtx

func (c *Cache) FlushCtx(ctx context.Context) error

FlushCtx is the context-aware variant of Flush. @group Invalidation

func (*Cache) Get

func (c *Cache) Get(key string) ([]byte, bool, error)

Get returns raw bytes for key when present. @group Reads

Example: get bytes

ctx := context.Background()
s := cache.NewMemoryStore(ctx)
c := cache.NewCache(s)
_ = c.Set("user:42", []byte("Ada"), 0)
value, ok, _ := c.Get("user:42")
fmt.Println(ok, string(value)) // true Ada

func (*Cache) GetCtx

func (c *Cache) GetCtx(ctx context.Context, key string) ([]byte, bool, error)

GetCtx is the context-aware variant of Get. @group Reads

func (*Cache) GetString

func (c *Cache) GetString(key string) (string, bool, error)

GetString returns a UTF-8 string value for key when present. @group Reads

Example: get string

ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
_ = c.SetString("user:42:name", "Ada", 0)
name, ok, _ := c.GetString("user:42:name")
fmt.Println(ok, name) // true Ada

func (*Cache) GetStringCtx

func (c *Cache) GetStringCtx(ctx context.Context, key string) (string, bool, error)

GetStringCtx is the context-aware variant of GetString. @group Reads

func (*Cache) Increment

func (c *Cache) Increment(key string, delta int64, ttl time.Duration) (int64, error)

Increment increments a numeric value and returns the result. @group Writes

Example: increment counter

ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
val, _ := c.Increment("rate:login:42", 1, time.Minute)
fmt.Println(val) // 1

func (*Cache) IncrementCtx

func (c *Cache) IncrementCtx(ctx context.Context, key string, delta int64, ttl time.Duration) (int64, error)

IncrementCtx is the context-aware variant of Increment. @group Writes

func (*Cache) Lock

func (c *Cache) Lock(key string, ttl, timeout time.Duration) (bool, error)

Lock waits until the lock is acquired or timeout elapses. @group Locking

Example: lock with timeout

ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
locked, err := c.Lock("job:sync", 10*time.Second, time.Second)
fmt.Println(err == nil, locked) // true true

func (*Cache) LockCtx

func (c *Cache) LockCtx(ctx context.Context, key string, ttl, retryInterval time.Duration) (bool, error)

LockCtx retries lock acquisition until success or context cancellation. @group Locking

func (*Cache) Pull

func (c *Cache) Pull(key string) ([]byte, bool, error)

Pull returns value and removes it from cache. @group Invalidation

Example: pull and delete

ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
_ = c.SetString("reset:token:42", "abc", time.Minute)
body, ok, _ := c.Pull("reset:token:42")
fmt.Println(ok, string(body)) // true abc

func (*Cache) PullCtx

func (c *Cache) PullCtx(ctx context.Context, key string) ([]byte, bool, error)

PullCtx is the context-aware variant of Pull. @group Invalidation

func (*Cache) RateLimit

func (c *Cache) RateLimit(key string, limit int64, window time.Duration) (bool, int64, error)

RateLimit increments key in a fixed window and reports whether requests are allowed. @group Rate Limiting

Example: fixed-window rate limit

ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
allowed, count, _ := c.RateLimit("rl:login:user:42", 5, time.Minute)
fmt.Println(allowed, count >= 1) // true true

func (*Cache) RateLimitCtx

func (c *Cache) RateLimitCtx(ctx context.Context, key string, limit int64, window time.Duration) (bool, int64, error)

RateLimitCtx is the context-aware variant of RateLimit. @group Rate Limiting

func (*Cache) RateLimitWithRemaining

func (c *Cache) RateLimitWithRemaining(key string, limit int64, window time.Duration) (bool, int64, int64, time.Time, error)

RateLimitWithRemaining increments a fixed-window counter and returns allowance metadata. @group Rate Limiting

Example: rate limit headers metadata

ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
allowed, count, remaining, resetAt, err := c.RateLimitWithRemaining("rl:api:ip:1.2.3.4", 100, time.Minute)
fmt.Println(err == nil, allowed, count >= 1, remaining >= 0, resetAt.After(time.Now()))

func (*Cache) RateLimitWithRemainingCtx

func (c *Cache) RateLimitWithRemainingCtx(ctx context.Context, key string, limit int64, window time.Duration) (bool, int64, int64, time.Time, error)

RateLimitWithRemainingCtx is the context-aware variant of RateLimitWithRemaining. @group Rate Limiting

func (*Cache) RefreshAhead

func (c *Cache) RefreshAhead(key string, ttl, refreshAhead time.Duration, fn func() ([]byte, error)) ([]byte, error)

RefreshAhead returns cached value immediately and refreshes asynchronously when near expiry. On miss, it computes and stores synchronously. @group Refresh Ahead

Example: refresh ahead

ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
body, err := c.RefreshAhead("dashboard:summary", time.Minute, 10*time.Second, func() ([]byte, error) {
	return []byte("payload"), nil
})
fmt.Println(err == nil, len(body) > 0) // true true

func (*Cache) RefreshAheadCtx

func (c *Cache) RefreshAheadCtx(ctx context.Context, key string, ttl, refreshAhead time.Duration, fn func(context.Context) ([]byte, error)) ([]byte, error)

RefreshAheadCtx is the context-aware variant of RefreshAhead. @group Refresh Ahead

func (*Cache) RememberBytes

func (c *Cache) RememberBytes(key string, ttl time.Duration, fn func() ([]byte, error)) ([]byte, error)

RememberBytes returns key value or computes/stores it when missing. @group Read Through

Example: remember bytes

ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
data, err := c.RememberBytes("dashboard:summary", time.Minute, func() ([]byte, error) {
	return []byte("payload"), nil
})
fmt.Println(err == nil, string(data)) // true payload

func (*Cache) RememberCtx

func (c *Cache) RememberCtx(ctx context.Context, key string, ttl time.Duration, fn func(context.Context) ([]byte, error)) ([]byte, error)

RememberCtx is the context-aware variant of RememberBytes. @group Read Through

func (*Cache) RememberStaleBytes

func (c *Cache) RememberStaleBytes(key string, ttl, staleTTL time.Duration, fn func() ([]byte, error)) ([]byte, bool, error)

RememberStaleBytes returns a fresh value when available, otherwise computes and caches it. If computing fails and a stale value exists, it returns the stale value. The returned bool is true when a stale fallback was used. @group Read Through

Example: stale fallback on upstream failure

ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
body, usedStale, err := c.RememberStaleBytes("profile:42", time.Minute, 10*time.Minute, func() ([]byte, error) {
	return []byte(`{"name":"Ada"}`), nil
})
fmt.Println(err == nil, usedStale, len(body) > 0)

func (*Cache) RememberStaleBytesCtx

func (c *Cache) RememberStaleBytesCtx(ctx context.Context, key string, ttl, staleTTL time.Duration, fn func(context.Context) ([]byte, error)) ([]byte, bool, error)

RememberStaleBytesCtx is the context-aware variant of RememberStaleBytes. @group Read Through

func (*Cache) RememberString

func (c *Cache) RememberString(key string, ttl time.Duration, fn func() (string, error)) (string, error)

RememberString returns key value or computes/stores it when missing. @group Read Through

Example: remember string

ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
val, err := c.RememberString("settings:mode", time.Minute, func() (string, error) {
	return "on", nil
})
fmt.Println(err == nil, val) // true on

func (*Cache) RememberStringCtx

func (c *Cache) RememberStringCtx(ctx context.Context, key string, ttl time.Duration, fn func(context.Context) (string, error)) (string, error)

RememberStringCtx is the context-aware variant of RememberString. @group Read Through

func (*Cache) Set

func (c *Cache) Set(key string, value []byte, ttl time.Duration) error

Set writes raw bytes to key. @group Writes

Example: set bytes with ttl

ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
fmt.Println(c.Set("token", []byte("abc"), time.Minute) == nil) // true

func (*Cache) SetCtx

func (c *Cache) SetCtx(ctx context.Context, key string, value []byte, ttl time.Duration) error

SetCtx is the context-aware variant of Set. @group Writes

func (*Cache) SetString

func (c *Cache) SetString(key string, value string, ttl time.Duration) error

SetString writes a string value to key. @group Writes

Example: set string

ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
fmt.Println(c.SetString("user:42:name", "Ada", time.Minute) == nil) // true

func (*Cache) SetStringCtx

func (c *Cache) SetStringCtx(ctx context.Context, key string, value string, ttl time.Duration) error

SetStringCtx is the context-aware variant of SetString. @group Writes

func (*Cache) Store

func (c *Cache) Store() Store

Store returns the underlying store implementation. @group Core

Example: access store

ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
fmt.Println(c.Store().Driver()) // memory

func (*Cache) TryLock

func (c *Cache) TryLock(key string, ttl time.Duration) (bool, error)

TryLock acquires a short-lived lock key when not already held. @group Locking

Example: try lock

ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
locked, _ := c.TryLock("job:sync", 10*time.Second)
fmt.Println(locked) // true

func (*Cache) TryLockCtx

func (c *Cache) TryLockCtx(ctx context.Context, key string, ttl time.Duration) (bool, error)

TryLockCtx is the context-aware variant of TryLock. @group Locking

func (*Cache) Unlock

func (c *Cache) Unlock(key string) error

Unlock releases a previously acquired lock key. @group Locking

Example: unlock key

ctx := context.Background()
c := cache.NewCache(cache.NewMemoryStore(ctx))
locked, _ := c.TryLock("job:sync", 10*time.Second)
if locked {
	_ = c.Unlock("job:sync")
}

func (*Cache) UnlockCtx

func (c *Cache) UnlockCtx(ctx context.Context, key string) error

UnlockCtx is the context-aware variant of Unlock. @group Locking

func (*Cache) WithObserver

func (c *Cache) WithObserver(o Observer) *Cache

WithObserver attaches an observer to receive operation events. @group Observability

type CacheAPI

CacheAPI is the composed application-facing interface for Cache.

type CompressionCodec

type CompressionCodec string

CompressionCodec represents a value compression algorithm.

const (
	CompressionNone   CompressionCodec = "none"
	CompressionGzip   CompressionCodec = "gzip"
	CompressionSnappy CompressionCodec = "snappy"
)

type CoreAPI

type CoreAPI interface {
	Driver() Driver
}

CoreAPI exposes basic cache metadata.

type CounterAPI

type CounterAPI interface {
	Increment(key string, delta int64, ttl time.Duration) (int64, error)
	IncrementCtx(ctx context.Context, key string, delta int64, ttl time.Duration) (int64, error)
	Decrement(key string, delta int64, ttl time.Duration) (int64, error)
	DecrementCtx(ctx context.Context, key string, delta int64, ttl time.Duration) (int64, error)
}

CounterAPI exposes increment/decrement operations.

type Driver

type Driver string

Driver identifies cache backend.

const (
	DriverNull      Driver = "null"
	DriverFile      Driver = "file"
	DriverMemory    Driver = "memory"
	DriverMemcached Driver = "memcached"
	DriverDynamo    Driver = "dynamodb"
	DriverSQL       Driver = "sql"
	DriverRedis     Driver = "redis"
	DriverNATS      Driver = "nats"
)

type DynamoAPI

type DynamoAPI interface {
	GetItem(ctx context.Context, params *dynamodb.GetItemInput, optFns ...func(*dynamodb.Options)) (*dynamodb.GetItemOutput, error)
	PutItem(ctx context.Context, params *dynamodb.PutItemInput, optFns ...func(*dynamodb.Options)) (*dynamodb.PutItemOutput, error)
	DeleteItem(ctx context.Context, params *dynamodb.DeleteItemInput, optFns ...func(*dynamodb.Options)) (*dynamodb.DeleteItemOutput, error)
	BatchWriteItem(ctx context.Context, params *dynamodb.BatchWriteItemInput, optFns ...func(*dynamodb.Options)) (*dynamodb.BatchWriteItemOutput, error)
	Scan(ctx context.Context, params *dynamodb.ScanInput, optFns ...func(*dynamodb.Options)) (*dynamodb.ScanOutput, error)
	CreateTable(ctx context.Context, params *dynamodb.CreateTableInput, optFns ...func(*dynamodb.Options)) (*dynamodb.CreateTableOutput, error)
	DescribeTable(ctx context.Context, params *dynamodb.DescribeTableInput, optFns ...func(*dynamodb.Options)) (*dynamodb.DescribeTableOutput, error)
}

DynamoAPI captures the subset of DynamoDB client methods used by the store.

type LockAPI

type LockAPI interface {
	TryLock(key string, ttl time.Duration) (bool, error)
	TryLockCtx(ctx context.Context, key string, ttl time.Duration) (bool, error)
	Lock(key string, ttl, timeout time.Duration) (bool, error)
	LockCtx(ctx context.Context, key string, ttl, retryInterval time.Duration) (bool, error)
	Unlock(key string) error
	UnlockCtx(ctx context.Context, key string) error
}

LockAPI exposes lock helpers based on cache keys.

type NATSKeyValue

type NATSKeyValue interface {
	Get(key string) (nats.KeyValueEntry, error)
	Put(key string, value []byte) (uint64, error)
	Create(key string, value []byte) (uint64, error)
	Update(key string, value []byte, last uint64) (uint64, error)
	Delete(key string, opts ...nats.DeleteOpt) error
	Purge(key string, opts ...nats.DeleteOpt) error
	ListKeys(opts ...nats.WatchOpt) (nats.KeyLister, error)
}

NATSKeyValue captures the subset of nats.KeyValue used by the store.

type Observer

type Observer interface {
	OnCacheOp(ctx context.Context, op string, key string, hit bool, err error, dur time.Duration, driver Driver)
}

Observer receives events for cache operations. It is called from Cache helpers after each operation completes.

type RateLimitAPI

type RateLimitAPI interface {
	RateLimit(key string, limit int64, window time.Duration) (bool, int64, error)
	RateLimitCtx(ctx context.Context, key string, limit int64, window time.Duration) (bool, int64, error)
	RateLimitWithRemaining(key string, limit int64, window time.Duration) (bool, int64, int64, time.Time, error)
	RateLimitWithRemainingCtx(ctx context.Context, key string, limit int64, window time.Duration) (bool, int64, int64, time.Time, error)
}

RateLimitAPI exposes rate limiting helpers.

type ReadAPI

type ReadAPI interface {
	Get(key string) ([]byte, bool, error)
	GetCtx(ctx context.Context, key string) ([]byte, bool, error)
	BatchGet(keys ...string) (map[string][]byte, error)
	BatchGetCtx(ctx context.Context, keys ...string) (map[string][]byte, error)
	GetString(key string) (string, bool, error)
	GetStringCtx(ctx context.Context, key string) (string, bool, error)
	Pull(key string) ([]byte, bool, error)
	PullCtx(ctx context.Context, key string) ([]byte, bool, error)
}

ReadAPI exposes read-oriented cache operations.

type RedisClient

type RedisClient interface {
	Get(ctx context.Context, key string) *redis.StringCmd
	Set(ctx context.Context, key string, value interface{}, expiration time.Duration) *redis.StatusCmd
	SetNX(ctx context.Context, key string, value interface{}, expiration time.Duration) *redis.BoolCmd
	IncrBy(ctx context.Context, key string, value int64) *redis.IntCmd
	Expire(ctx context.Context, key string, expiration time.Duration) *redis.BoolCmd
	Del(ctx context.Context, keys ...string) *redis.IntCmd
	Scan(ctx context.Context, cursor uint64, match string, count int64) *redis.ScanCmd
}

RedisClient captures the subset of redis.Client used by the store.

type RefreshAheadAPI

type RefreshAheadAPI interface {
	RefreshAhead(key string, ttl, refreshAhead time.Duration, fn func() ([]byte, error)) ([]byte, error)
	RefreshAheadCtx(ctx context.Context, key string, ttl, refreshAhead time.Duration, fn func(context.Context) ([]byte, error)) ([]byte, error)
}

RefreshAheadAPI exposes refresh-ahead helpers.

type RememberAPI

type RememberAPI interface {
	RememberBytes(key string, ttl time.Duration, fn func() ([]byte, error)) ([]byte, error)
	RememberCtx(ctx context.Context, key string, ttl time.Duration, fn func(context.Context) ([]byte, error)) ([]byte, error)
	RememberString(key string, ttl time.Duration, fn func() (string, error)) (string, error)
	RememberStringCtx(ctx context.Context, key string, ttl time.Duration, fn func(context.Context) (string, error)) (string, error)
	RememberStaleBytes(key string, ttl, staleTTL time.Duration, fn func() ([]byte, error)) ([]byte, bool, error)
	RememberStaleBytesCtx(ctx context.Context, key string, ttl, staleTTL time.Duration, fn func(context.Context) ([]byte, error)) ([]byte, bool, error)
}

RememberAPI exposes remember and stale-remember helpers.

type Store

type Store interface {
	Driver() Driver
	Get(ctx context.Context, key string) ([]byte, bool, error)
	Set(ctx context.Context, key string, value []byte, ttl time.Duration) error
	Add(ctx context.Context, key string, value []byte, ttl time.Duration) (bool, error)
	Increment(ctx context.Context, key string, delta int64, ttl time.Duration) (int64, error)
	Decrement(ctx context.Context, key string, delta int64, ttl time.Duration) (int64, error)
	Delete(ctx context.Context, key string) error
	DeleteMany(ctx context.Context, keys ...string) error
	Flush(ctx context.Context) error
}

Store is the shared app cache contract.

func NewDynamoStore

func NewDynamoStore(ctx context.Context, cfg StoreConfig, opts ...StoreOption) Store

NewDynamoStore is a convenience for a DynamoDB-backed store. @group Constructors

Example: dynamo helper (stub)

ctx := context.Background()
store := cache.NewDynamoStore(ctx, cache.StoreConfig{DynamoEndpoint: "http://localhost:8000"})
fmt.Println(store.Driver()) // dynamodb

func NewFileStore

func NewFileStore(ctx context.Context, dir string, opts ...StoreOption) Store

NewFileStore is a convenience for a filesystem-backed store. @group Constructors

Example: file helper

ctx := context.Background()
store := cache.NewFileStore(ctx, "/tmp/my-cache")
fmt.Println(store.Driver()) // file

func NewMemcachedStore

func NewMemcachedStore(ctx context.Context, addrs []string, opts ...StoreOption) Store

NewMemcachedStore is a convenience for a memcached-backed store. @group Constructors

Example: memcached helper

ctx := context.Background()
store := cache.NewMemcachedStore(ctx, []string{"127.0.0.1:11211"})
fmt.Println(store.Driver()) // memcached

func NewMemoStore

func NewMemoStore(store Store) Store

NewMemoStore decorates store with per-process read memoization.

Behavior:

  • First Get hits the backing store, clones the value, and memoizes it in-process.
  • Subsequent Get for the same key returns the memoized clone (no backend call).
  • Any write/delete/flush invalidates the memo entry so local reads stay in sync with changes made through this process.
  • Memo data is per-process only; other processes or external writers will not invalidate it. Use only when that staleness window is acceptable.

@group Memoization

Example: memoize a backing store

ctx := context.Background()
base := cache.NewMemoryStore(ctx)
memo := cache.NewMemoStore(base)
c := cache.NewCache(memo)
fmt.Println(c.Driver()) // memory

func NewMemoryStore

func NewMemoryStore(ctx context.Context, opts ...StoreOption) Store

NewMemoryStore is a convenience for an in-process store with optional overrides. @group Constructors

Example: memory helper

ctx := context.Background()
store := cache.NewMemoryStore(ctx)
fmt.Println(store.Driver()) // memory

func NewNATSStore

func NewNATSStore(ctx context.Context, kv NATSKeyValue, opts ...StoreOption) Store

NewNATSStore is a convenience for a NATS JetStream KeyValue-backed store. @group Constructors

Example: NATS helper

ctx := context.Background()
var kv cache.NATSKeyValue // provided by your NATS setup
store := cache.NewNATSStore(ctx, kv, cache.WithPrefix("app"))
fmt.Println(store.Driver()) // nats

func NewNullStore

func NewNullStore(ctx context.Context, opts ...StoreOption) Store

NewNullStore is a no-op store useful for tests where caching should be disabled. @group Constructors

Example: null helper

ctx := context.Background()
store := cache.NewNullStore(ctx)
fmt.Println(store.Driver()) // null

func NewRedisStore

func NewRedisStore(ctx context.Context, client RedisClient, opts ...StoreOption) Store

NewRedisStore is a convenience for a redis-backed store. Redis client is required. @group Constructors

Example: redis helper

ctx := context.Background()
redisClient := redis.NewClient(&redis.Options{Addr: "127.0.0.1:6379"})
store := cache.NewRedisStore(ctx, redisClient, cache.WithPrefix("app"))
fmt.Println(store.Driver()) // redis

func NewSQLStore

func NewSQLStore(ctx context.Context, driverName, dsn, table string, opts ...StoreOption) Store

NewSQLStore builds a SQL-backed store (postgres, mysql, sqlite). @group Constructors

Example: sqlite helper

ctx := context.Background()
store := cache.NewSQLStore(ctx, "sqlite", "file:cache.db?cache=shared&mode=rwc", "cache_entries")
fmt.Println(store.Driver()) // sql

Example: postgres helper

dsnPg := "postgres://user:pass@localhost:5432/app?sslmode=disable"
storePg := cache.NewSQLStore(ctx, "pgx", dsnPg, "cache_entries")
fmt.Println(storePg.Driver()) // sql

Example: mysql helper

dsnMy := "user:pass@tcp(localhost:3306)/app?parseTime=true"
storeMy := cache.NewSQLStore(ctx, "mysql", dsnMy, "cache_entries")
fmt.Println(storeMy.Driver()) // sql

func NewStore

func NewStore(ctx context.Context, cfg StoreConfig) Store

NewStore returns a concrete store for the requested driver. Caller is responsible for providing any driver-specific dependencies. @group Constructors

Example: select driver explicitly

ctx := context.Background()
store := cache.NewStore(ctx, cache.StoreConfig{
	Driver: cache.DriverMemory,
})
fmt.Println(store.Driver()) // memory

func NewStoreWith

func NewStoreWith(ctx context.Context, driver Driver, opts ...StoreOption) Store

NewStoreWith builds a store using a driver and a set of functional options. Required data (e.g., Redis client) must be provided via options when needed. @group Constructors

Example: memory store (options)

ctx := context.Background()
store := cache.NewStoreWith(ctx, cache.DriverMemory)
fmt.Println(store.Driver()) // memory

Example: redis store (options)

redisClient := redis.NewClient(&redis.Options{Addr: "127.0.0.1:6379"})
store = cache.NewStoreWith(ctx, cache.DriverRedis,
	cache.WithRedisClient(redisClient),
	cache.WithPrefix("app"),
	cache.WithDefaultTTL(5*time.Minute),
)
fmt.Println(store.Driver()) // redis

type StoreConfig

type StoreConfig struct {
	Driver Driver

	// DefaultTTL is used when a call provides ttl <= 0.
	DefaultTTL time.Duration

	// MemoryCleanupInterval controls in-process cache eviction.
	MemoryCleanupInterval time.Duration

	// Prefix is used by shared backends (e.g. redis keys).
	Prefix string

	// RedisClient is required when DriverRedis is used.
	RedisClient RedisClient
	// NATSKeyValue is required when DriverNATS is used.
	NATSKeyValue NATSKeyValue
	// NATSBucketTTL uses raw values and bucket-level MaxAge (no per-key TTL envelope).
	NATSBucketTTL bool

	// FileDir controls where file driver stores cache entries.
	FileDir string

	// MemcachedAddresses are required when DriverMemcached is used (host:port).
	MemcachedAddresses []string

	// DynamoEndpoint is the HTTP endpoint for DynamoDB (e.g., localstack/dynamodb-local).
	DynamoEndpoint string
	// DynamoRegion sets the AWS region used for signing.
	DynamoRegion string
	// DynamoTable is the table name used for cache entries.
	DynamoTable string
	// DynamoClient allows injecting a preconfigured DynamoDB client.
	DynamoClient DynamoAPI

	// SQLDriverName is the database/sql driver name: "postgres", "mysql", or "sqlite".
	SQLDriverName string
	// SQLDSN is the driver-specific DSN.
	SQLDSN string
	// SQLTable is the table name for the SQL driver.
	SQLTable string

	// Compression controls value compression before storage.
	Compression CompressionCodec
	// MaxValueBytes enforces a maximum value size (post-compression) when > 0.
	MaxValueBytes int

	// EncryptionKey enables at-rest encryption when provided (16/24/32 bytes AES key).
	EncryptionKey []byte
}

StoreConfig controls how a Store is constructed.

type StoreOption

type StoreOption func(StoreConfig) StoreConfig

StoreOption mutates StoreConfig when constructing a store.

func WithCompression

func WithCompression(codec CompressionCodec) StoreOption

WithCompression enables value compression using the chosen codec. @group Options

Example: gzip compression

ctx := context.Background()
store := cache.NewStoreWith(ctx, cache.DriverMemory, cache.WithCompression(cache.CompressionGzip))
fmt.Println(store.Driver()) // memory

func WithDefaultTTL

func WithDefaultTTL(ttl time.Duration) StoreOption

WithDefaultTTL overrides the fallback TTL used when ttl <= 0. @group Options

Example: override default TTL

ctx := context.Background()
store := cache.NewStoreWith(ctx, cache.DriverMemory, cache.WithDefaultTTL(30*time.Second))
fmt.Println(store.Driver()) // memory

func WithDynamoClient

func WithDynamoClient(client DynamoAPI) StoreOption

WithDynamoClient injects a pre-built DynamoDB client. @group Options

Example: inject dynamo client

ctx := context.Background()
var client cache.DynamoAPI // assume already configured
store := cache.NewStoreWith(ctx, cache.DriverDynamo, cache.WithDynamoClient(client))
fmt.Println(store.Driver()) // dynamodb

func WithDynamoEndpoint

func WithDynamoEndpoint(endpoint string) StoreOption

WithDynamoEndpoint sets the DynamoDB endpoint (useful for local testing). @group Options

Example: dynamo local endpoint

ctx := context.Background()
store := cache.NewStoreWith(ctx, cache.DriverDynamo, cache.WithDynamoEndpoint("http://localhost:8000"))
fmt.Println(store.Driver()) // dynamodb

func WithDynamoRegion

func WithDynamoRegion(region string) StoreOption

WithDynamoRegion sets the DynamoDB region for requests. @group Options

Example: set dynamo region

ctx := context.Background()
store := cache.NewStoreWith(ctx, cache.DriverDynamo, cache.WithDynamoRegion("us-west-2"))
fmt.Println(store.Driver()) // dynamodb

func WithDynamoTable

func WithDynamoTable(table string) StoreOption

WithDynamoTable sets the table used by the DynamoDB driver. @group Options

Example: custom dynamo table

ctx := context.Background()
store := cache.NewStoreWith(ctx, cache.DriverDynamo, cache.WithDynamoTable("cache_entries"))
fmt.Println(store.Driver()) // dynamodb

func WithEncryptionKey

func WithEncryptionKey(key []byte) StoreOption

WithEncryptionKey enables at-rest encryption using the provided AES key (16/24/32 bytes). @group Options

Example: encrypt values

ctx := context.Background()
key := []byte("01234567890123456789012345678901")
store := cache.NewStoreWith(ctx, cache.DriverFile, cache.WithEncryptionKey(key))
fmt.Println(store.Driver()) // file

func WithFileDir

func WithFileDir(dir string) StoreOption

WithFileDir sets the directory used by the file driver. @group Options

Example: set file dir

ctx := context.Background()
store := cache.NewStoreWith(ctx, cache.DriverFile, cache.WithFileDir("/tmp/cache"))
fmt.Println(store.Driver()) // file

func WithMaxValueBytes

func WithMaxValueBytes(limit int) StoreOption

WithMaxValueBytes sets a per-entry size limit (0 disables the check). @group Options

Example: limit value size

ctx := context.Background()
store := cache.NewStoreWith(ctx, cache.DriverMemory, cache.WithMaxValueBytes(1024))
fmt.Println(store.Driver()) // memory

func WithMemcachedAddresses

func WithMemcachedAddresses(addrs ...string) StoreOption

WithMemcachedAddresses sets memcached server addresses (host:port). @group Options

Example: memcached cluster

ctx := context.Background()
store := cache.NewStoreWith(ctx, cache.DriverMemcached, cache.WithMemcachedAddresses("127.0.0.1:11211"))
fmt.Println(store.Driver()) // memcached

func WithMemoryCleanupInterval

func WithMemoryCleanupInterval(interval time.Duration) StoreOption

WithMemoryCleanupInterval overrides the sweep interval for the memory driver. @group Options

Example: custom memory sweep

ctx := context.Background()
store := cache.NewStoreWith(ctx, cache.DriverMemory, cache.WithMemoryCleanupInterval(5*time.Minute))
fmt.Println(store.Driver()) // memory

func WithNATSBucketTTL

func WithNATSBucketTTL(enabled bool) StoreOption

WithNATSBucketTTL toggles bucket-level TTL mode for DriverNATS. When enabled, values are stored as raw bytes and per-operation ttl values are ignored. @group Options

Example: enable NATS bucket-level TTL mode

ctx := context.Background()
var kv cache.NATSKeyValue // provided by your NATS setup
store := cache.NewStoreWith(ctx, cache.DriverNATS,
	cache.WithNATSKeyValue(kv),
	cache.WithNATSBucketTTL(true),
)
fmt.Println(store.Driver()) // nats

func WithNATSKeyValue

func WithNATSKeyValue(kv NATSKeyValue) StoreOption

WithNATSKeyValue sets the NATS JetStream KeyValue bucket; required when using DriverNATS. @group Options

Example: inject NATS key-value bucket

ctx := context.Background()
var kv cache.NATSKeyValue // provided by your NATS setup
store := cache.NewStoreWith(ctx, cache.DriverNATS, cache.WithNATSKeyValue(kv))
fmt.Println(store.Driver()) // nats

func WithPrefix

func WithPrefix(prefix string) StoreOption

WithPrefix sets the key prefix for shared backends (e.g., redis). @group Options

Example: prefix keys

ctx := context.Background()
store := cache.NewStoreWith(ctx, cache.DriverRedis, cache.WithPrefix("svc"))
fmt.Println(store.Driver()) // redis

func WithRedisClient

func WithRedisClient(client RedisClient) StoreOption

WithRedisClient sets the redis client; required when using DriverRedis. @group Options

Example: inject redis client

ctx := context.Background()
rdb := redis.NewClient(&redis.Options{Addr: "127.0.0.1:6379"})
store := cache.NewStoreWith(ctx, cache.DriverRedis, cache.WithRedisClient(rdb))
fmt.Println(store.Driver()) // redis

func WithSQL

func WithSQL(driverName, dsn, table string) StoreOption

WithSQL configures the SQL driver (driver name + DSN + optional table). @group Options

Example: sqlite via options

ctx := context.Background()
store := cache.NewStoreWith(ctx, cache.DriverSQL,
	cache.WithSQL("sqlite", "file::memory:?cache=shared", "cache_entries"),
	cache.WithPrefix("svc"),
)
fmt.Println(store.Driver()) // sql

type ValueCodec

type ValueCodec[T any] struct {
	Encode func(T) ([]byte, error)
	Decode func([]byte) (T, error)
}

ValueCodec defines how to encode/decode values for RememberValue.

type WriteAPI

type WriteAPI interface {
	Set(key string, value []byte, ttl time.Duration) error
	SetCtx(ctx context.Context, key string, value []byte, ttl time.Duration) error
	SetString(key string, value string, ttl time.Duration) error
	SetStringCtx(ctx context.Context, key string, value string, ttl time.Duration) error
	BatchSet(values map[string][]byte, ttl time.Duration) error
	BatchSetCtx(ctx context.Context, values map[string][]byte, ttl time.Duration) error
	Add(key string, value []byte, ttl time.Duration) (bool, error)
	AddCtx(ctx context.Context, key string, value []byte, ttl time.Duration) (bool, error)
	Delete(key string) error
	DeleteCtx(ctx context.Context, key string) error
	DeleteMany(keys ...string) error
	DeleteManyCtx(ctx context.Context, keys ...string) error
	Flush() error
	FlushCtx(ctx context.Context) error
}

WriteAPI exposes write and invalidation operations.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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