Help us shape the future of Go! Take the 2026 Go Developer Survey

cache

package
v0.21.0 Latest Latest
Warning

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

Go to latest
Published: Oct 17, 2026 License: MIT Imports: 14 Imported by: 2

Documentation

Overview

Package cache stores values with a TTL behind a Store (memory, database; Redis in drivers/redis). Values are JSON-encoded, so typed reads use the generic functions:

user, err := cache.Remember(ctx, app.Cache, "user:42", time.Hour, func(ctx context.Context) (User, error) {
	return orm.QueryOf[User](db).Find(ctx, 42)
})

Cache wraps a Store with a key prefix and adds Put, Forget, Increment and distributed locks (Cache.NewLock); Get and Remember decode typed values. Apps get one from app.Cache(), configured by CACHE_STORE.

See https://github.com/AlexGalhardo/vukem/blob/main/docs/subsystems.md#cache.

Index

Examples

Constants

This section is empty.

Variables

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

ErrNotAcquired is returned by Lock.Block when the wait expired.

Functions

func Get

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

Get reads key into T; ok is false when the key is missing or expired.

Example
package main

import (
	"context"
	"fmt"
	"time"

	"github.com/AlexGalhardo/vukem/cache"
)

func main() {
	ctx := context.Background()
	c := cache.New(cache.NewMemory(1000), "")

	_ = c.Put(ctx, "greeting", "hello", time.Minute)

	v, ok, err := cache.Get[string](ctx, c, "greeting")
	fmt.Println(v, ok, err)

	_, ok, _ = cache.Get[string](ctx, c, "missing")
	fmt.Println(ok)
}
Output:
hello true <nil>
false

func Remember

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

Remember returns the cached value or computes it with fn and stores it for ttl. Concurrent misses for the same key in this process run fn once (singleflight), so an expired hot key does not stampede the database.

Example
package main

import (
	"context"
	"fmt"
	"time"

	"github.com/AlexGalhardo/vukem/cache"
)

type user struct {
	ID   int64
	Name string
}

func main() {
	ctx := context.Background()
	c := cache.New(cache.NewMemory(1000), "app:")

	loads := 0
	load := func(context.Context) (user, error) {
		loads++
		return user{ID: 42, Name: "Ada"}, nil
	}

	first, _ := cache.Remember(ctx, c, "user:42", time.Hour, load)
	second, _ := cache.Remember(ctx, c, "user:42", time.Hour, load)
	fmt.Println(first.Name, second.Name, "loads:", loads)
}
Output:
Ada Ada loads: 1

Types

type Cache

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

Cache is a Store with a key prefix, JSON encoding and stampede protection.

func New

func New(store Store, prefix string) *Cache

New returns a Cache; prefix namespaces keys ("app:").

func (*Cache) Flush

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

Flush deletes everything in the store.

func (*Cache) Forget

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

Forget deletes keys.

func (*Cache) Increment

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

Increment adds delta to the integer at key (counters, rate limits).

func (*Cache) NewLock

func (c *Cache) NewLock(name string, ttl time.Duration) *Lock

NewLock prepares a lock on name that expires after ttl if never released.

Example
package main

import (
	"context"
	"fmt"
	"time"

	"github.com/AlexGalhardo/vukem/cache"
)

func main() {
	ctx := context.Background()
	c := cache.New(cache.NewMemory(1000), "")

	lock := c.NewLock("reports", time.Minute)
	got, _ := lock.TryAcquire(ctx)
	again, _ := c.NewLock("reports", time.Minute).TryAcquire(ctx)
	fmt.Println(got, again)

	_ = lock.Release(ctx)
}
Output:
true false

func (*Cache) Put

func (c *Cache) Put(ctx context.Context, key string, v any, ttl time.Duration) error

Put stores v under key for ttl (0 = no expiry).

func (*Cache) Store

func (c *Cache) Store() Store

Store returns the backend.

type Database

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

Database stores entries in a table (SQLite, Postgres or MySQL): cache(key TEXT PRIMARY KEY, value TEXT NOT NULL, expires_at BIGINT) with expires_at in Unix milliseconds (0 = never). CreateTable creates it. On MySQL key and value are binary (VARBINARY, LONGBLOB) so lookups stay exact and case-sensitive.

func NewDatabase

func NewDatabase(db *database.DB, table string) (*Database, error)

NewDatabase returns a database store using table (default "cache").

func (*Database) Add

func (d *Database) Add(ctx context.Context, key string, value []byte, ttl time.Duration) (bool, error)

Add implements Store: expired rows are replaced, live ones kept.

func (*Database) CreateTable

func (d *Database) CreateTable(ctx context.Context) error

CreateTable creates the cache table if missing.

func (*Database) Delete

func (d *Database) Delete(ctx context.Context, keys ...string) error

Delete implements Store.

func (*Database) DeleteIf

func (d *Database) DeleteIf(ctx context.Context, key string, value []byte) (bool, error)

DeleteIf implements Store.

func (*Database) Flush

func (d *Database) Flush(ctx context.Context) error

Flush implements Store.

func (*Database) Get

func (d *Database) Get(ctx context.Context, key string) ([]byte, bool, error)

Get implements Store.

func (*Database) Increment

func (d *Database) Increment(ctx context.Context, key string, delta int64, ttl time.Duration) (int64, error)

Increment implements Store (atomically, in a transaction).

func (*Database) Prune

func (d *Database) Prune(ctx context.Context) (int64, error)

Prune deletes expired rows (schedule it, e.g. hourly).

func (*Database) Set

func (d *Database) Set(ctx context.Context, key string, value []byte, ttl time.Duration) error

Set implements Store.

type Lock

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

Lock is a distributed (store-wide) mutual exclusion lock.

func (*Lock) Block

func (l *Lock) Block(ctx context.Context, wait, interval time.Duration) error

Block waits up to wait for the lock, polling every interval.

func (*Lock) Release

func (l *Lock) Release(ctx context.Context) error

Release frees the lock if this Lock still owns it.

func (*Lock) TryAcquire

func (l *Lock) TryAcquire(ctx context.Context) (bool, error)

TryAcquire takes the lock if it is free.

type Memory

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

Memory is an in-process LRU store with TTLs. MaxEntries bounds memory (least recently used entries are evicted).

func NewMemory

func NewMemory(maxEntries int) *Memory

NewMemory returns a memory store holding at most maxEntries (0 = 10000).

func (*Memory) Add

func (m *Memory) Add(_ context.Context, key string, value []byte, ttl time.Duration) (bool, error)

Add implements Store.

func (*Memory) Delete

func (m *Memory) Delete(_ context.Context, keys ...string) error

Delete implements Store.

func (*Memory) DeleteIf

func (m *Memory) DeleteIf(_ context.Context, key string, value []byte) (bool, error)

DeleteIf implements Store.

func (*Memory) Flush

func (m *Memory) Flush(context.Context) error

Flush implements Store.

func (*Memory) Get

func (m *Memory) Get(_ context.Context, key string) ([]byte, bool, error)

Get implements Store.

func (*Memory) Increment

func (m *Memory) Increment(_ context.Context, key string, delta int64, ttl time.Duration) (int64, error)

Increment implements Store.

func (*Memory) Len

func (m *Memory) Len() int

Len returns the number of stored entries (expired ones included until they are touched).

func (*Memory) Set

func (m *Memory) Set(_ context.Context, key string, value []byte, ttl time.Duration) error

Set implements Store.

type Store

type Store interface {
	Get(ctx context.Context, key string) ([]byte, bool, error)
	Set(ctx context.Context, key string, value []byte, ttl time.Duration) error
	// Add sets key only when it is absent (or expired) and reports whether
	// it did; locks rely on it being atomic.
	Add(ctx context.Context, key string, value []byte, ttl time.Duration) (bool, error)
	Delete(ctx context.Context, keys ...string) error
	// DeleteIf deletes key only when it holds value (lock release).
	DeleteIf(ctx context.Context, key string, value []byte) (bool, error)
	// Increment adds delta to an integer value (missing keys start at 0
	// with ttl) and returns the new value.
	Increment(ctx context.Context, key string, delta int64, ttl time.Duration) (int64, error)
	Flush(ctx context.Context) error
}

Store is a cache backend. Keys arrive already prefixed.

Directories

Path Synopsis
Package cachetest is the conformance suite every cache.Store passes (memory and database in core, Redis in drivers/redis).
Package cachetest is the conformance suite every cache.Store passes (memory and database in core, Redis in drivers/redis).

Jump to

Keyboard shortcuts

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