caching API

caching

package

API reference for the caching package.

I
interface

Cache

Cache defines the generic caching contract.

core/caching/cache.go:17-27
type Cache interface

Example

cache := caching.NewInMemory[string](caching.WithTTL[string](5*time.Minute))
cache.Set(ctx, "key", "value", 0)
val, ok, err := cache.Get(ctx, "key")

Methods

Get
Method

Parameters

key string

Returns

T
bool
error
func Get(...)
Set
Method

Parameters

key string
value T

Returns

error
func Set(...)
Invalidate
Method

Parameters

key string

Returns

error
func Invalidate(...)
S
struct

entry

entry holds a cached value with its expiry time.

core/caching/cache.go:30-33
type entry struct

Fields

Name Type Description
value T
expiry time.Time
S
struct

InMemoryCache

InMemoryCache is a thread-safe in-memory implementation of Cache.

core/caching/cache.go:41-46
type InMemoryCache struct

Example

cache := caching.NewInMemory[string]()
cache.Set(ctx, "greeting", "hello", time.Minute)

Fields

Name Type Description
mu sync.RWMutex
data map[string]entry[T]
defaultTTL time.Duration
maxEntries int
T
type

InMemoryOption

InMemoryOption configures an InMemoryCache.

core/caching/cache.go:49-49
type InMemoryOption func(*InMemoryCache[T])
F
function

NewInMemory

NewInMemory creates a new InMemoryCache with optional configuration.

Parameters

opts
...InMemoryOption[T]

Returns

*InMemoryCache[T]
core/caching/cache.go:59-68
func NewInMemory[T any](opts ...InMemoryOption[T]) *InMemoryCache[T]

{
	c := &InMemoryCache[T]{
		data:       make(map[string]entry[T]),
		maxEntries: 10_000,
	}
	for _, opt := range opts {
		opt(c)
	}
	return c
}

Example

cache := caching.NewInMemory[string](
    caching.WithTTL[string](time.Minute),
    caching.WithMaxEntries[string](1000),
)
F
function

WithTTL

WithTTL sets the default TTL for cache entries.

Parameters

Returns

InMemoryOption[T]
core/caching/cache.go:71-73
func WithTTL[T any](d time.Duration) InMemoryOption[T]

{
	return func(c *InMemoryCache[T]) { c.defaultTTL = d }
}
F
function

WithMaxEntries

WithMaxEntries sets the maximum number of entries before eviction.

Parameters

n
int

Returns

InMemoryOption[T]
core/caching/cache.go:76-78
func WithMaxEntries[T any](n int) InMemoryOption[T]

{
	return func(c *InMemoryCache[T]) { c.maxEntries = n }
}
F
function

TestInMemoryCacheSetGetInvalidate

Parameters

core/caching/cache_test.go:9-30
func TestInMemoryCacheSetGetInvalidate(t *testing.T)

{
	cache := NewInMemory[string]()
	ctx := context.Background()

	if err := cache.Set(ctx, "key", "value", 0); err != nil {
		t.Fatalf("Set() error = %v", err)
	}
	got, ok, err := cache.Get(ctx, "key")
	if err != nil {
		t.Fatalf("Get() error = %v", err)
	}
	if !ok || got != "value" {
		t.Fatalf("Get() = %q, %v", got, ok)
	}

	if err := cache.Invalidate(ctx, "key"); err != nil {
		t.Fatalf("Invalidate() error = %v", err)
	}
	if _, ok, _ := cache.Get(ctx, "key"); ok {
		t.Fatal("Get() found invalidated key")
	}
}
F
function

TestInMemoryCacheTTL

Parameters

core/caching/cache_test.go:32-44
func TestInMemoryCacheTTL(t *testing.T)

{
	cache := NewInMemory[string](WithTTL[string](time.Nanosecond))
	ctx := context.Background()

	if err := cache.Set(ctx, "key", "value", 0); err != nil {
		t.Fatalf("Set() error = %v", err)
	}
	time.Sleep(time.Millisecond)

	if _, ok, _ := cache.Get(ctx, "key"); ok {
		t.Fatal("Get() found expired key")
	}
}
F
function

TestInMemoryCacheMaxEntries

Parameters

core/caching/cache_test.go:46-56
func TestInMemoryCacheMaxEntries(t *testing.T)

{
	cache := NewInMemory[string](WithMaxEntries[string](1))
	ctx := context.Background()

	cache.Set(ctx, "a", "A", 0)
	cache.Set(ctx, "b", "B", 0)

	if cache.Len() != 1 {
		t.Fatalf("Len() = %d, want 1", cache.Len())
	}
}
I
interface

DistributedCache

DistributedCache is a byte-level cache backend for distributed systems.
Implementations include Redis, Memcached, etc.

core/caching/distributed.go:12-16
type DistributedCache interface

Methods

Get
Method

Parameters

key string

Returns

[]byte
bool
error
func Get(...)
Set
Method

Parameters

key string
value []byte

Returns

error
func Set(...)
Delete
Method

Parameters

key string

Returns

error
func Delete(...)
S
struct

DistributedBridge

DistributedBridge adapts a DistributedCache to a typed Cache[T] using JSON.

core/caching/distributed.go:19-21
type DistributedBridge struct

Fields

Name Type Description
inner DistributedCache
F
function

NewDistributedBridge

NewDistributedBridge creates a typed cache bridge over a DistributedCache backend.

Parameters

Returns

*DistributedBridge[T]
core/caching/distributed.go:24-26
func NewDistributedBridge[T any](backend DistributedCache) *DistributedBridge[T]

{
	return &DistributedBridge[T]{inner: backend}
}
S
struct
Implements: DistributedCache

DistributedInMemory

DistributedInMemory is an in-memory implementation of DistributedCache
suitable for testing and single-process scenarios.

core/caching/distributed.go:61-66
type DistributedInMemory struct

Methods

Get
Method

Get implements DistributedCache.Get.

Parameters

key string

Returns

[]byte
bool
error
func (*DistributedInMemory) Get(ctx context.Context, key string) ([]byte, bool, error)
{
	m.mu.RLock()
	e, ok := m.data[key]
	m.mu.RUnlock()

	if !ok {
		return nil, false, nil
	}

	if !e.expiry.IsZero() && time.Now().After(e.expiry) {
		m.mu.Lock()
		delete(m.data, key)
		m.mu.Unlock()
		return nil, false, nil
	}

	return append([]byte(nil), e.value...), true, nil
}
Set
Method

Set implements DistributedCache.Set.

Parameters

key string
value []byte

Returns

error
func (*DistributedInMemory) Set(ctx context.Context, key string, value []byte, ttl time.Duration) error
{
	e := distributedEntry{value: append([]byte(nil), value...)}
	if ttl > 0 {
		e.expiry = time.Now().Add(ttl)
	} else if m.ttl > 0 {
		e.expiry = time.Now().Add(m.ttl)
	}

	m.mu.Lock()
	if m.maxEntries > 0 {
		if _, exists := m.data[key]; !exists && len(m.data) >= m.maxEntries {
			for candidate := range m.data {
				delete(m.data, candidate)
				break
			}
		}
	}
	m.data[key] = e
	m.mu.Unlock()
	return nil
}
Delete
Method

Delete implements DistributedCache.Delete.

Parameters

key string

Returns

error
func (*DistributedInMemory) Delete(ctx context.Context, key string) error
{
	m.mu.Lock()
	delete(m.data, key)
	m.mu.Unlock()
	return nil
}

Fields

Name Type Description
mu sync.RWMutex
data map[string]distributedEntry
ttl time.Duration
maxEntries int
S
struct

distributedEntry

core/caching/distributed.go:68-71
type distributedEntry struct

Fields

Name Type Description
value []byte
expiry time.Time
F
function

NewDistributedInMemory

NewDistributedInMemory creates a new in-memory distributed cache.

Parameters

opts
...DistributedInMemoryOption
core/caching/distributed.go:74-83
func NewDistributedInMemory(opts ...DistributedInMemoryOption) *DistributedInMemory

{
	c := &DistributedInMemory{
		data:       make(map[string]distributedEntry),
		maxEntries: 10_000,
	}
	for _, opt := range opts {
		opt(c)
	}
	return c
}
T
type

DistributedInMemoryOption

DistributedInMemoryOption configures a DistributedInMemory cache.

core/caching/distributed.go:86-86
type DistributedInMemoryOption func(*DistributedInMemory)
F
function

WithDistributedTTL

WithDistributedTTL sets the default TTL for entries.

core/caching/distributed.go:89-91
func WithDistributedTTL(d time.Duration) DistributedInMemoryOption

{
	return func(c *DistributedInMemory) { c.ttl = d }
}
F
function

WithDistributedMaxEntries

WithDistributedMaxEntries sets the maximum number of entries before eviction.

Parameters

n
int
core/caching/distributed.go:94-96
func WithDistributedMaxEntries(n int) DistributedInMemoryOption

{
	return func(c *DistributedInMemory) { c.maxEntries = n }
}
S
struct

cachedUser

core/caching/distributed_test.go:9-11
type cachedUser struct

Fields

Name Type Description
Name string json:"name"
F
function

TestDistributedBridgeRoundTrip

Parameters

core/caching/distributed_test.go:13-35
func TestDistributedBridgeRoundTrip(t *testing.T)

{
	ctx := context.Background()
	backend := NewDistributedInMemory()
	cache := NewDistributedBridge[cachedUser](backend)

	if err := cache.Set(ctx, "user", cachedUser{Name: "alice"}, 0); err != nil {
		t.Fatalf("Set() error = %v", err)
	}
	got, ok, err := cache.Get(ctx, "user")
	if err != nil {
		t.Fatalf("Get() error = %v", err)
	}
	if !ok || got.Name != "alice" {
		t.Fatalf("Get() = %+v, %v", got, ok)
	}

	if err := cache.Invalidate(ctx, "user"); err != nil {
		t.Fatalf("Invalidate() error = %v", err)
	}
	if _, ok, _ := cache.Get(ctx, "user"); ok {
		t.Fatal("Get() found invalidated key")
	}
}
F
function

TestDistributedInMemoryTTL

Parameters

core/caching/distributed_test.go:37-49
func TestDistributedInMemoryTTL(t *testing.T)

{
	ctx := context.Background()
	backend := NewDistributedInMemory(WithDistributedTTL(time.Nanosecond))

	if err := backend.Set(ctx, "key", []byte("value"), 0); err != nil {
		t.Fatalf("Set() error = %v", err)
	}
	time.Sleep(time.Millisecond)

	if _, ok, _ := backend.Get(ctx, "key"); ok {
		t.Fatal("Get() found expired key")
	}
}
F
function

TestDistributedInMemoryCopiesValues

Parameters

core/caching/distributed_test.go:51-69
func TestDistributedInMemoryCopiesValues(t *testing.T)

{
	ctx := context.Background()
	backend := NewDistributedInMemory()
	value := []byte("value")
	if err := backend.Set(ctx, "key", value, 0); err != nil {
		t.Fatal(err)
	}
	value[0] = 'X'

	got, ok, err := backend.Get(ctx, "key")
	if err != nil || !ok || string(got) != "value" {
		t.Fatalf("Get() = %q, %v, %v", got, ok, err)
	}
	got[0] = 'Y'
	again, _, _ := backend.Get(ctx, "key")
	if string(again) != "value" {
		t.Fatalf("caller mutated cached data: %q", again)
	}
}
F
function

TestDistributedInMemoryMaxEntries

Parameters

core/caching/distributed_test.go:71-86
func TestDistributedInMemoryMaxEntries(t *testing.T)

{
	ctx := context.Background()
	backend := NewDistributedInMemory(WithDistributedMaxEntries(1))
	if err := backend.Set(ctx, "one", []byte("1"), 0); err != nil {
		t.Fatal(err)
	}
	if err := backend.Set(ctx, "two", []byte("2"), 0); err != nil {
		t.Fatal(err)
	}
	backend.mu.RLock()
	size := len(backend.data)
	backend.mu.RUnlock()
	if size != 1 {
		t.Fatalf("entry count = %d, want 1", size)
	}
}