cache

package
v1.3.0 Latest Latest
Warning

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

Go to latest
Published: Jul 16, 2026 License: MIT Imports: 19 Imported by: 0

README

Cache

Multi-tier distributed cache for Nimbus. Supports memory, Redis, Memcached, DynamoDB, and Cloudflare KV.

Boot

cache.Boot(nil)  // uses CACHE_DRIVER from .env

Remember (getOrSet)

user, err := cache.RememberT("user:1", 10*time.Minute, func() (User, error) {
    var u User
    err := database.Get().First(&u, 1).Error
    return u, err
})

Get and Set

cache.Set("app:settings", map[string]any{"theme": "dark"}, 5*time.Minute)
settings, ok := cache.Get("app:settings")

cache.SetForever("app:version", "2.0.0")  // never expires

if cache.Has("products:featured") { /* key exists */ }
if cache.Missing("products:featured") { /* key does not exist */ }

token, ok := cache.Pull("verify:token:123")  // get and delete in one call

Namespaces

usersCache := cache.Namespace("users")
usersCache.Set("42", user, 10*time.Minute)  // stores under "users:42"
usersCache.Clear()  // clears all "users:*" (Memory & Redis)

Backends

Driver Env Notes
memory (default) Single process
redis REDIS_URL Prefix invalidation
memcached MEMCACHED_SERVERS Key limit 250 bytes
dynamodb CACHE_DYNAMO_TABLE, AWS_REGION Table: pk (string), val, ttl
cloudflare CLOUDFLARE_* Min TTL 60s

Invalidation

cache.Delete("user:1")
cache.InvalidatePrefix("user:")  // Memory & Redis

ORM integration

database.RegisterHooks(db, "users", database.Hooks{
    AfterSave: func(db *gorm.DB) {
        if u, ok := db.Statement.Model.(*User); ok {
            cache.Delete(fmt.Sprintf("user:%d", u.ID))
        }
    },
})

// Query caching
database.CachedFind(db.Model(&User{}), "users:list", 10*time.Minute, &users)

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrLockNotAcquired = errors.New("cache: lock not acquired")

ErrLockNotAcquired is returned when a lock cannot be acquired.

Functions

func AtomicLock

func AtomicLock(store Store, key string, ttl time.Duration, fn func() error) error

AtomicLock acquires a lock, calls fn, then releases the lock. If the lock cannot be acquired, returns ErrLockNotAcquired.

err := cache.AtomicLock(store, "expensive-query", 30*time.Second, func() error {
    // rebuild cache
    return nil
})

func Delete

func Delete(key string) error

Delete removes a key from the global cache.

func Get

func Get(key string) (any, bool)

Get returns a value from the global cache.

func Has

func Has(key string) bool

Has returns true if the key exists in the cache.

func InvalidatePrefix

func InvalidatePrefix(prefix string) error

InvalidatePrefix deletes all keys with the given prefix. Supported by MemoryStore and RedisStore. Other stores no-op.

func Missing

func Missing(key string) bool

Missing returns true if the key does not exist in the cache.

func Pull

func Pull(key string) (any, bool)

Pull retrieves a value and immediately deletes it. Useful for one-time-use data (e.g. flash messages).

func Remember

func Remember(key string, ttl time.Duration, fn func() (any, error)) (any, error)

Remember gets from cache or calls fn, stores the result, and returns it.

func RememberT

func RememberT[T any](key string, ttl time.Duration, fn func() (T, error)) (T, error)

RememberT is a type-safe Remember. The callback returns T; the value is JSON-serialized for distributed stores.

func Set

func Set(key string, value any, ttl time.Duration) error

Set stores a value in the global cache. Uses default store if Boot was not called.

func SetForever

func SetForever(key string, value any) error

SetForever stores a value that never expires (TTL = 0 is treated as no expiry for memory store).

func SetGlobal

func SetGlobal(s Store)

SetGlobal sets the global cache store.

Types

type BootConfig

type BootConfig struct {
	Driver                string // memory, redis, memcached, dynamodb, cloudflare
	RedisURL              string
	MemcachedServers      string // comma-separated, e.g. "localhost:11211"
	DynamoTable           string
	DynamoRegion          string
	CloudflareAccountID   string
	CloudflareNamespaceID string
	CloudflareAPIToken    string
	DefaultTTL            time.Duration
}

BootConfig configures cache boot. Pass nil for env-based config.

type CloudflareKVStore

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

CloudflareKVStore uses Cloudflare Workers KV for edge-distributed caching. Requires CLOUDFLARE_ACCOUNT_ID, CLOUDFLARE_NAMESPACE_ID, CLOUDFLARE_API_TOKEN. KV is eventually consistent; writes may take up to 60s to propagate globally.

func NewCloudflareKVStore

func NewCloudflareKVStore(accountID, namespaceID, apiToken string) *CloudflareKVStore

NewCloudflareKVStore creates a Cloudflare KV cache store.

func NewCloudflareKVStoreWithPrefix

func NewCloudflareKVStoreWithPrefix(accountID, namespaceID, apiToken, prefix string) *CloudflareKVStore

NewCloudflareKVStoreWithPrefix creates a Cloudflare KV store with a custom key prefix.

func (*CloudflareKVStore) Delete

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

Delete removes a key.

func (*CloudflareKVStore) Get

func (c *CloudflareKVStore) Get(key string) (any, bool)

Get returns the value and true if found.

func (*CloudflareKVStore) Remember

func (c *CloudflareKVStore) Remember(key string, ttl time.Duration, fn func() (any, error)) (any, error)

Remember returns the cached value or calls fn, stores the result, and returns it.

func (*CloudflareKVStore) Set

func (c *CloudflareKVStore) Set(key string, value any, ttl time.Duration) error

Set stores a value. Values are JSON-serialized. Min TTL: 60 seconds for Cloudflare KV.

type DynamoDBStore

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

DynamoDBStore uses AWS DynamoDB for distributed caching. Requires a table with partition key "pk" (string) and optional "ttl" (number) for expiration. Enable TTL on the table for the "ttl" attribute to auto-delete expired items.

func NewDynamoDBStore

func NewDynamoDBStore(cfg aws.Config, tableName string) *DynamoDBStore

NewDynamoDBStore creates a DynamoDB cache store.

func NewDynamoDBStoreWithPrefix

func NewDynamoDBStoreWithPrefix(cfg aws.Config, tableName, prefix string) *DynamoDBStore

NewDynamoDBStoreWithPrefix creates a DynamoDB store with a custom key prefix.

func (*DynamoDBStore) Delete

func (d *DynamoDBStore) Delete(key string) error

Delete removes a key.

func (*DynamoDBStore) EnsureTable

func (d *DynamoDBStore) EnsureTable(ctx context.Context) error

EnsureTable creates the cache table if it does not exist. Call once during setup. Table: pk (string, partition key), val (string), ttl (number, optional for TTL).

func (*DynamoDBStore) Get

func (d *DynamoDBStore) Get(key string) (any, bool)

Get returns the value and true if found.

func (*DynamoDBStore) Remember

func (d *DynamoDBStore) Remember(key string, ttl time.Duration, fn func() (any, error)) (any, error)

Remember returns the cached value or calls fn, stores the result, and returns it.

func (*DynamoDBStore) Set

func (d *DynamoDBStore) Set(key string, value any, ttl time.Duration) error

Set stores a value. Values are JSON-serialized.

type Lock

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

Lock provides a simple distributed-friendly mutual exclusion lock backed by the cache store. It prevents thundering herd / cache stampede by ensuring only one goroutine (or one process, for distributed stores like Redis) rebuilds a cache entry at a time.

Usage:

lock := cache.NewLock(store, "lock:rebuild-reports", 30*time.Second)
acquired, err := lock.Acquire()
if err != nil || !acquired {
    return // another worker is rebuilding
}
defer lock.Release()
// ... rebuild expensive data ...

func NewLock

func NewLock(store Store, key string, ttl time.Duration) *Lock

NewLock creates a cache lock with the given key and TTL.

func (*Lock) Acquire

func (l *Lock) Acquire() (bool, error)

Acquire attempts to acquire the lock. Returns true if successful.

func (*Lock) Block

func (l *Lock) Block(timeout time.Duration, interval time.Duration) (bool, error)

Block attempts to acquire the lock, retrying at the given interval until the timeout is reached. Returns true if the lock was acquired.

func (*Lock) Release

func (l *Lock) Release() error

Release releases the lock (only if we are the owner).

type MemcachedStore

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

MemcachedStore uses Memcached for distributed caching.

func NewMemcachedStore

func NewMemcachedStore(servers ...string) *MemcachedStore

NewMemcachedStore creates a Memcached cache store. servers: comma-separated list like "localhost:11211" or "10.0.0.1:11211,10.0.0.2:11211"

func NewMemcachedStoreWithPrefix

func NewMemcachedStoreWithPrefix(servers []string, prefix string) *MemcachedStore

NewMemcachedStoreWithPrefix creates a Memcached store with a custom key prefix.

func (*MemcachedStore) Delete

func (m *MemcachedStore) Delete(key string) error

Delete removes a key.

func (*MemcachedStore) Get

func (m *MemcachedStore) Get(key string) (any, bool)

Get returns the value and true if found.

func (*MemcachedStore) Remember

func (m *MemcachedStore) Remember(key string, ttl time.Duration, fn func() (any, error)) (any, error)

Remember returns the cached value or calls fn, stores the result, and returns it.

func (*MemcachedStore) Set

func (m *MemcachedStore) Set(key string, value any, ttl time.Duration) error

Set stores a value. Values are JSON-serialized. Memcached key limit is 250 bytes.

type MemoryStore

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

MemoryStore is an in-memory cache (driver: memory). Single-process only; not shared across instances.

func NewMemoryStore

func NewMemoryStore() *MemoryStore

NewMemoryStore returns a new in-memory cache.

func (*MemoryStore) Delete

func (m *MemoryStore) Delete(key string) error

Delete removes a key.

func (*MemoryStore) Get

func (m *MemoryStore) Get(key string) (any, bool)

Get returns the value and true if found and not expired.

func (*MemoryStore) InvalidatePrefix

func (m *MemoryStore) InvalidatePrefix(prefix string) error

InvalidatePrefix deletes all keys with the given prefix.

func (*MemoryStore) Remember

func (m *MemoryStore) Remember(key string, ttl time.Duration, fn func() (any, error)) (any, error)

Remember returns the cached value or calls fn, stores the result, and returns it.

func (*MemoryStore) Set

func (m *MemoryStore) Set(key string, value any, ttl time.Duration) error

Set stores a value. Zero TTL = no expiry.

type NamespaceStore

type NamespaceStore interface {
	Store
	Clear() error
}

NamespaceStore is a Store scoped to a namespace, with Clear to remove all entries in that namespace.

func Namespace

func Namespace(prefix string) NamespaceStore

Namespace returns a Store that prefixes all keys with the given namespace. Use for grouping related cache entries and clearing them together.

Example:

usersCache := cache.Namespace("users")
usersCache.Set("42", user, 10*time.Minute)  // stores under "users:42"
usersCache.Clear()                          // clears all "users:*" (Memory & Redis)

type PrefixInvalidator

type PrefixInvalidator interface {
	Store
	InvalidatePrefix(prefix string) error
}

PrefixInvalidator is implemented by stores that support prefix-based invalidation.

type RedisStore

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

RedisStore uses Redis for distributed caching.

func NewRedisStore

func NewRedisStore(client *redis.Client) *RedisStore

NewRedisStore creates a Redis cache store.

func NewRedisStoreWithPrefix

func NewRedisStoreWithPrefix(client *redis.Client, prefix string) *RedisStore

NewRedisStoreWithPrefix creates a Redis store with a custom key prefix.

func (*RedisStore) Delete

func (r *RedisStore) Delete(key string) error

Delete removes a key.

func (*RedisStore) Get

func (r *RedisStore) Get(key string) (any, bool)

Get returns the value and true if found.

func (*RedisStore) InvalidatePrefix

func (r *RedisStore) InvalidatePrefix(prefix string) error

InvalidatePrefix deletes all keys with the given prefix using SCAN.

func (*RedisStore) Remember

func (r *RedisStore) Remember(key string, ttl time.Duration, fn func() (any, error)) (any, error)

Remember returns the cached value or calls fn, stores the result, and returns it.

func (*RedisStore) Set

func (r *RedisStore) Set(key string, value any, ttl time.Duration) error

Set stores a value. Values are JSON-serialized.

type Store

type Store interface {
	Set(key string, value any, ttl time.Duration) error
	Get(key string) (any, bool)
	Delete(key string) error
	Remember(key string, ttl time.Duration, fn func() (any, error)) (any, error)
}

Store is the cache interface. All backends implement it. Values are JSON-serialized for distributed stores (Redis, Memcached, DynamoDB).

var Default Store = NewMemoryStore()

Default is the fallback in-memory store when Boot was not called.

func Boot

func Boot(cfg *BootConfig) Store

Boot initializes the cache from config/env and sets it globally.

func GetGlobal

func GetGlobal() Store

GetGlobal returns the global cache store.

Jump to

Keyboard shortcuts

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