cache

package
v1.12.5 Latest Latest
Warning

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

Go to latest
Published: Oct 28, 2026 License: BSD-3-Clause Imports: 13 Imported by: 0

Documentation

Overview

Package cache provides a comprehensive caching solution with multiple backends and advanced features like TTL, LRU eviction, serialization, and distributed caching.

It supports in-memory caching with LRU eviction, Redis-backed distributed caching, and provides features like:

  • TTL (Time To Live) support
  • LRU (Least Recently Used) eviction
  • Automatic serialization/deserialization
  • Cache statistics and monitoring
  • Namespace support for multi-tenant applications
  • Bulk operations (GetMulti, SetMulti, DeleteMulti)
  • Cache warming and preloading
  • Event callbacks (OnSet, OnGet, OnDelete, OnEvict)
  • Compression support for large values
  • Circuit breaker pattern for external cache failures

Example usage:

package main

import (
	"context"
	"time"

	"github.com/valentin-kaiser/go-core/cache"
)

func main() {
	// Create an in-memory cache with LRU eviction
	memCache := cache.NewMemoryCache().
		WithMaxSize(1000).
		WithDefaultTTL(time.Hour).
		WithLRUEviction(true)

	// Create a Redis-backed cache
	redisCache := cache.NewRedisCache(cache.RedisConfig{
		Addr:     "localhost:6379",
		Password: "",
		DB:       0,
	})

	// Create a multi-tier cache (L1: memory, L2: Redis)
	tieredCache := cache.NewTieredCache(memCache, redisCache)

	// Use the cache
	ctx := context.Background()

	// Set a value with TTL
	err := tieredCache.Set(ctx, "user:123", user, time.Minute*30)
	if err != nil {
		panic(err)
	}

	// Get a value
	var cachedUser User
	found, err := tieredCache.Get(ctx, "user:123", &cachedUser)
	if err != nil {
		panic(err)
	}

	if found {
		fmt.Printf("Found user: %+v\n", cachedUser)
	}
}

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type BaseCache

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

BaseCache provides common functionality for cache implementations

func NewBaseCache

func NewBaseCache(config Config) *BaseCache

NewBaseCache creates a new base cache with the given configuration

func (*BaseCache) GetConfig

func (bc *BaseCache) GetConfig() Config

GetConfig returns the cache configuration

func (*BaseCache) GetStats

func (bc *BaseCache) GetStats() Stats

GetStats returns a copy of the current cache statistics

type Cache

type Cache interface {
	// Get retrieves a value from the cache and deserializes it into the provided destination
	Get(ctx context.Context, key string, dest interface{}) (bool, error)

	// Set stores a value in the cache with the specified TTL
	Set(ctx context.Context, key string, value interface{}, ttl time.Duration) error

	// Delete removes a value from the cache
	Delete(ctx context.Context, key string) error

	// Exists checks if a key exists in the cache
	Exists(ctx context.Context, key string) (bool, error)

	// Clear removes all entries from the cache
	Clear(ctx context.Context) error

	// GetMulti retrieves multiple values from the cache
	GetMulti(ctx context.Context, keys []string) (map[string]interface{}, error)

	// SetMulti stores multiple values in the cache
	SetMulti(ctx context.Context, items map[string]interface{}, ttl time.Duration) error

	// DeleteMulti removes multiple values from the cache
	DeleteMulti(ctx context.Context, keys []string) error

	// GetTTL returns the remaining TTL for a key
	GetTTL(ctx context.Context, key string) (time.Duration, error)

	// SetTTL updates the TTL for an existing key
	SetTTL(ctx context.Context, key string, ttl time.Duration) error

	// GetStats returns cache statistics
	GetStats() Stats

	// Close closes the cache and releases resources
	Close() error
}

Cache defines the interface for cache implementations

type Config

type Config struct {
	MaxSize         int64         `json:"max_size"`
	DefaultTTL      time.Duration `json:"default_ttl"`
	CleanupInterval time.Duration `json:"cleanup_interval"`
	EnableLRU       bool          `json:"enable_lru"`
	EnableStats     bool          `json:"enable_stats"`
	EnableEvents    bool          `json:"enable_events"`
	Namespace       string        `json:"namespace"`
	// Shards splits a MemoryCache into this many parts with their own locks. 0 or 1 keeps one
	// part, which is an exact LRU; more parts let concurrent writers run in parallel but make
	// eviction approximate: MaxSize is divided exactly between the parts (so the cache never holds
	// more than MaxSize items) and a full part evicts its own least recently used item. With a
	// MaxSize below Shards, some parts hold nothing.
	Shards       int          `json:"shards,omitempty"`
	Serializer   Serializer   `json:"-"`
	EventHandler EventHandler `json:"-"`
}

Config holds common configuration for cache implementations

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns a default cache configuration

func (*Config) Changed

func (c *Config) Changed(n *Config) bool

Changed checks if the cache configuration has changed compared to another configuration.

type Error

type Error struct {
	Op  string
	Key string
	Err error
}

Error represents a cache-specific error

func NewCacheError

func NewCacheError(op, key string, err error) *Error

NewCacheError creates a new cache error

func (*Error) Error

func (e *Error) Error() string

Error implements the error interface

func (*Error) Unwrap

func (e *Error) Unwrap() error

Unwrap returns the underlying error

type Event

type Event struct {
	Type      EventType   `json:"type"`
	Key       string      `json:"key"`
	Value     interface{} `json:"value,omitempty"`
	Timestamp time.Time   `json:"timestamp"`
	Namespace string      `json:"namespace,omitempty"`
	Error     error       `json:"error,omitempty"`
}

Event represents a cache event

type EventHandler

type EventHandler func(event Event)

EventHandler is a function that handles cache events

type EventType

type EventType int

EventType represents cache event types

const (
	// EventSet represents a cache set event
	EventSet EventType = iota
	// EventGet represents a cache get event
	EventGet
	// EventDelete represents a cache delete event
	EventDelete
	// EventEvict represents a cache eviction event
	EventEvict
	// EventExpire represents a cache expiration event
	EventExpire
	// EventClear represents a cache clear event
	EventClear
)

func (EventType) String

func (e EventType) String() string

String returns the string representation of the event type

type InMemorySerializer added in v1.12.3

type InMemorySerializer interface {
	Serializer
	// Keep returns what the cache stores for the value
	Keep(value interface{}) (interface{}, error)
	// Restore copies a stored value into dest, which is a pointer
	Restore(kept interface{}, dest interface{}) error
}

InMemorySerializer is implemented by serializers that let an in-process cache keep values as they are, without encoding them. MemoryCache uses it when its serializer implements it.

type Item

type Item struct {
	Key       string        `json:"key"`
	Value     interface{}   `json:"value"`
	ExpiresAt time.Time     `json:"expires_at"`
	CreatedAt time.Time     `json:"created_at"`
	UpdatedAt time.Time     `json:"updated_at"`
	AccessAt  time.Time     `json:"access_at"`
	TTL       time.Duration `json:"ttl"`
	Size      int64         `json:"size"`
	Namespace string        `json:"namespace,omitempty"`
}

Item represents a cache item with metadata

func (*Item) IsExpired

func (i *Item) IsExpired() bool

IsExpired checks if the item has expired

type JSONSerializer

type JSONSerializer struct{}

JSONSerializer implements JSON serialization

func (*JSONSerializer) Deserialize

func (s *JSONSerializer) Deserialize(data []byte, dest interface{}) error

Deserialize deserializes JSON data into the destination

func (*JSONSerializer) Serialize

func (s *JSONSerializer) Serialize(value interface{}) ([]byte, error)

Serialize serializes a value to JSON

type MemoryCache

type MemoryCache struct {
	*BaseCache
	// contains filtered or unexported fields
}

MemoryCache implements an in-memory cache with LRU eviction support

func NewMemoryCache

func NewMemoryCache() *MemoryCache

NewMemoryCache creates a new in-memory cache with default configuration. The default settings include LRU eviction, 1000 item max size, 1 hour default TTL, and 5-minute cleanup intervals. For custom settings, use NewMemoryCacheWithConfig.

Example usage:

cache := cache.NewMemoryCache()
err := cache.Set(ctx, "key", "value", time.Hour)

func NewMemoryCacheWithConfig

func NewMemoryCacheWithConfig(config Config) *MemoryCache

NewMemoryCacheWithConfig creates a new in-memory cache with custom configuration. This allows fine-tuning of cache behavior including size limits, TTL settings, LRU eviction policies, cleanup intervals, and serialization options.

Config.Shards splits the cache into that many independent parts, each with its own lock, so concurrent writers do not wait for each other. MaxSize is then divided between the shards, and eviction picks the least recently used item of the shard that is full, not of the whole cache.

Example usage:

config := cache.Config{
	MaxSize:         5000,
	DefaultTTL:      time.Minute * 30,
	CleanupInterval: time.Minute,
	EnableLRU:       true,
}
cache := cache.NewMemoryCacheWithConfig(config)

func (*MemoryCache) Clear

func (mc *MemoryCache) Clear(_ context.Context) error

Clear removes all entries from the cache

func (*MemoryCache) Close

func (mc *MemoryCache) Close() error

Close closes the cache and stops the cleanup goroutine

func (*MemoryCache) Delete

func (mc *MemoryCache) Delete(_ context.Context, key string) error

Delete removes a value from the cache

func (*MemoryCache) DeleteMulti

func (mc *MemoryCache) DeleteMulti(ctx context.Context, keys []string) error

DeleteMulti removes multiple values from the cache

func (*MemoryCache) Exists

func (mc *MemoryCache) Exists(_ context.Context, key string) (bool, error)

Exists checks if a key exists in the cache

func (*MemoryCache) Get

func (mc *MemoryCache) Get(_ context.Context, key string, dest interface{}) (bool, error)

Get retrieves a value from the cache

func (*MemoryCache) GetKeys

func (mc *MemoryCache) GetKeys() []string

GetKeys returns all keys in the cache (useful for debugging)

func (*MemoryCache) GetMemoryUsage

func (mc *MemoryCache) GetMemoryUsage() int64

GetMemoryUsage returns the current memory usage in bytes

func (*MemoryCache) GetMulti

func (mc *MemoryCache) GetMulti(ctx context.Context, keys []string) (map[string]interface{}, error)

GetMulti retrieves multiple values from the cache

func (*MemoryCache) GetSize

func (mc *MemoryCache) GetSize() int64

GetSize returns the current number of items in the cache

func (*MemoryCache) GetTTL

func (mc *MemoryCache) GetTTL(_ context.Context, key string) (time.Duration, error)

GetTTL returns the remaining TTL for a key

func (*MemoryCache) Set

func (mc *MemoryCache) Set(_ context.Context, key string, value interface{}, ttl time.Duration) error

Set stores a value in the cache

func (*MemoryCache) SetMulti

func (mc *MemoryCache) SetMulti(ctx context.Context, items map[string]interface{}, ttl time.Duration) error

SetMulti stores multiple values in the cache

func (*MemoryCache) SetTTL

func (mc *MemoryCache) SetTTL(_ context.Context, key string, ttl time.Duration) error

SetTTL updates the TTL for an existing key

func (*MemoryCache) WithCleanupInterval

func (mc *MemoryCache) WithCleanupInterval(interval time.Duration) *MemoryCache

WithCleanupInterval sets the interval for cleaning up expired items

func (*MemoryCache) WithDefaultTTL

func (mc *MemoryCache) WithDefaultTTL(ttl time.Duration) *MemoryCache

WithDefaultTTL sets the default TTL for cache items

func (*MemoryCache) WithEventHandler

func (mc *MemoryCache) WithEventHandler(handler EventHandler) *MemoryCache

WithEventHandler sets the event handler for cache events

func (*MemoryCache) WithLRUEviction

func (mc *MemoryCache) WithLRUEviction(enabled bool) *MemoryCache

WithLRUEviction enables or disables LRU eviction

func (*MemoryCache) WithMaxSize

func (mc *MemoryCache) WithMaxSize(maxSize int64) *MemoryCache

WithMaxSize sets the maximum number of items in the cache

type NativeSerializer added in v1.12.3

type NativeSerializer struct{ JSONSerializer }

NativeSerializer keeps values in memory as Go values instead of JSON, which makes reads of a MemoryCache several times faster. Serialize and Deserialize are still JSON, so the same serializer works for Redis or the second level of a TieredCache.

Values are not copied deeply: a struct is copied by value, but maps, slices and pointers inside it are shared with the caller and with every reader. Treat cached values as read-only, or use the JSON serializer, whose reads each get their own copy. The size of an item is not tracked, so GetMemoryUsage reports 0 for a cache that uses this serializer.

func (*NativeSerializer) Keep added in v1.12.3

func (s *NativeSerializer) Keep(value interface{}) (interface{}, error)

Keep stores the value; a pointer is stored as the value it points to

func (*NativeSerializer) Restore added in v1.12.3

func (s *NativeSerializer) Restore(kept interface{}, dest interface{}) error

Restore assigns the stored value to dest. When the types do not match it falls back to a JSON round trip.

type NoOpSerializer

type NoOpSerializer struct{}

NoOpSerializer implements no serialization (for already serialized data)

func (*NoOpSerializer) Deserialize

func (s *NoOpSerializer) Deserialize(data []byte, dest interface{}) error

Deserialize copies the data to the destination if it's *[]byte or *string

func (*NoOpSerializer) Serialize

func (s *NoOpSerializer) Serialize(value interface{}) ([]byte, error)

Serialize returns the value as-is if it's []byte, otherwise returns an error

type RedisCache

type RedisCache struct {
	*BaseCache
	// contains filtered or unexported fields
}

RedisCache implements a Redis-backed cache

func NewRedisCache

func NewRedisCache(config RedisConfig) *RedisCache

NewRedisCache creates a new Redis-backed cache with default cache configuration. It establishes a new Redis client connection using the provided Redis configuration and applies default cache settings (LRU eviction, 1 hour TTL, etc.).

Example usage:

config := cache.RedisConfig{
	Addr:     "localhost:6379",
	Password: "",
	DB:       0,
}
cache := cache.NewRedisCache(config)

func NewRedisCacheWithCacheConfig

func NewRedisCacheWithCacheConfig(redisConfig RedisConfig, cacheConfig Config) *RedisCache

NewRedisCacheWithCacheConfig creates a new Redis-backed cache with both custom Redis connection settings and cache configuration. This provides the most flexibility for configuring both the Redis client and cache behavior.

func NewRedisCacheWithClient

func NewRedisCacheWithClient(client *redis.Client) *RedisCache

NewRedisCacheWithClient creates a new Redis-backed cache using an existing Redis client. This is useful when you want to share a Redis client across multiple cache instances or when you need custom Redis client configuration that's not supported by RedisConfig.

func NewRedisCacheWithConfig

func NewRedisCacheWithConfig(client *redis.Client, config Config) *RedisCache

NewRedisCacheWithConfig creates a new Redis-backed cache with an existing Redis client and custom cache configuration. This allows fine-tuning of cache behavior while reusing an existing Redis connection.

func (*RedisCache) Clear

func (rc *RedisCache) Clear(ctx context.Context) error

Clear removes all entries from the cache (only works with namespace)

func (*RedisCache) Close

func (rc *RedisCache) Close() error

Close closes the Redis client

func (*RedisCache) Decrement

func (rc *RedisCache) Decrement(ctx context.Context, key string, delta int64) (int64, error)

Decrement atomically decrements a numeric value

func (*RedisCache) Delete

func (rc *RedisCache) Delete(ctx context.Context, key string) error

Delete removes a value from the cache

func (*RedisCache) DeleteMulti

func (rc *RedisCache) DeleteMulti(ctx context.Context, keys []string) error

DeleteMulti removes multiple values from the cache

func (*RedisCache) Exists

func (rc *RedisCache) Exists(ctx context.Context, key string) (bool, error)

Exists checks if a key exists in the cache

func (*RedisCache) FlushDB

func (rc *RedisCache) FlushDB(ctx context.Context) error

FlushDB flushes the current Redis database

func (*RedisCache) Get

func (rc *RedisCache) Get(ctx context.Context, key string, dest interface{}) (bool, error)

Get retrieves a value from the cache

func (*RedisCache) GetClient

func (rc *RedisCache) GetClient() *redis.Client

GetClient returns the underlying Redis client for advanced operations

func (*RedisCache) GetInfo

func (rc *RedisCache) GetInfo(ctx context.Context) (map[string]string, error)

GetInfo returns Redis server information

func (*RedisCache) GetMulti

func (rc *RedisCache) GetMulti(ctx context.Context, keys []string) (map[string]interface{}, error)

GetMulti retrieves multiple values from the cache

func (*RedisCache) GetSet

func (rc *RedisCache) GetSet(ctx context.Context, key string, value interface{}) (interface{}, bool, error)

GetSet atomically sets a new value and returns the old value

func (*RedisCache) GetTTL

func (rc *RedisCache) GetTTL(ctx context.Context, key string) (time.Duration, error)

GetTTL returns the remaining TTL for a key

func (*RedisCache) Increment

func (rc *RedisCache) Increment(ctx context.Context, key string, delta int64) (int64, error)

Increment atomically increments a numeric value

func (*RedisCache) Ping

func (rc *RedisCache) Ping(ctx context.Context) error

Ping tests the Redis connection

func (*RedisCache) Set

func (rc *RedisCache) Set(ctx context.Context, key string, value interface{}, ttl time.Duration) error

Set stores a value in the cache

func (*RedisCache) SetMulti

func (rc *RedisCache) SetMulti(ctx context.Context, items map[string]interface{}, ttl time.Duration) error

SetMulti stores multiple values in the cache

func (*RedisCache) SetNX

func (rc *RedisCache) SetNX(ctx context.Context, key string, value interface{}, ttl time.Duration) (bool, error)

SetNX sets a key only if it doesn't exist (atomic operation)

func (*RedisCache) SetTTL

func (rc *RedisCache) SetTTL(ctx context.Context, key string, ttl time.Duration) error

SetTTL updates the TTL for an existing key

func (*RedisCache) WithDefaultTTL

func (rc *RedisCache) WithDefaultTTL(ttl time.Duration) *RedisCache

WithDefaultTTL sets the default TTL for cache items

func (*RedisCache) WithEventHandler

func (rc *RedisCache) WithEventHandler(handler EventHandler) *RedisCache

WithEventHandler sets the event handler for cache events

func (*RedisCache) WithNamespace

func (rc *RedisCache) WithNamespace(namespace string) *RedisCache

WithNamespace sets the namespace for cache keys

type RedisConfig

type RedisConfig struct {
	Addr         string        `json:"addr"`
	Password     string        `json:"password"`
	DB           int           `json:"db"`
	PoolSize     int           `json:"pool_size"`
	MinIdleConns int           `json:"min_idle_conns"`
	MaxRetries   int           `json:"max_retries"`
	DialTimeout  time.Duration `json:"dial_timeout"`
	ReadTimeout  time.Duration `json:"read_timeout"`
	WriteTimeout time.Duration `json:"write_timeout"`
	IdleTimeout  time.Duration `json:"idle_timeout"`
}

RedisConfig holds configuration for Redis cache

func DefaultRedisConfig

func DefaultRedisConfig() RedisConfig

DefaultRedisConfig returns a default Redis configuration

func (*RedisConfig) Changed

func (rc *RedisConfig) Changed(n *RedisConfig) bool

Changed checks if the Redis configuration has changed compared to another configuration.

type Serializer

type Serializer interface {
	Serialize(value interface{}) ([]byte, error)
	Deserialize(data []byte, dest interface{}) error
}

Serializer defines the interface for value serialization

type Stats

type Stats struct {
	Hits        int64     `json:"hits"`
	Misses      int64     `json:"misses"`
	Sets        int64     `json:"sets"`
	Deletes     int64     `json:"deletes"`
	Evictions   int64     `json:"evictions"`
	Size        int64     `json:"size"`
	MaxSize     int64     `json:"max_size"`
	HitRatio    float64   `json:"hit_ratio"`
	Memory      int64     `json:"memory_bytes"`
	Errors      int64     `json:"errors"`
	LastError   string    `json:"last_error,omitempty"`
	LastErrorAt time.Time `json:"last_error_at,omitempty"`
}

Stats represents cache statistics

type TieredCache

type TieredCache struct {
	*BaseCache
	// contains filtered or unexported fields
}

TieredCache implements a multi-tier cache system (e.g., L1: Memory, L2: Redis)

func NewTieredCache

func NewTieredCache(l1Cache, l2Cache Cache) *TieredCache

NewTieredCache creates a new multi-tier cache with L1 and L2 cache implementations. The L1 cache is typically a fast, small cache (like memory) while L2 is a larger, persistent cache (like Redis). Reads check L1 first, then L2, with automatic promotion of hot data to L1. Writes go to both tiers for consistency.

Example usage:

memCache := cache.NewMemoryCache()
redisCache := cache.NewRedisCache(redisConfig)
tiered := cache.NewTieredCache(memCache, redisCache)

func NewTieredCacheWithConfig

func NewTieredCacheWithConfig(l1Cache, l2Cache Cache, config Config) *TieredCache

NewTieredCacheWithConfig creates a new tiered cache with custom configuration. This allows fine-tuning of cache behavior across both tiers while maintaining the performance benefits of multi-tier caching architecture.

func (*TieredCache) Clear

func (tc *TieredCache) Clear(ctx context.Context) error

Clear removes all entries from both L1 and L2 caches

func (*TieredCache) Close

func (tc *TieredCache) Close() error

Close closes both cache implementations

func (*TieredCache) Delete

func (tc *TieredCache) Delete(ctx context.Context, key string) error

Delete removes a value from both L1 and L2 caches

func (*TieredCache) DeleteMulti

func (tc *TieredCache) DeleteMulti(ctx context.Context, keys []string) error

DeleteMulti removes multiple values from both L1 and L2 caches

func (*TieredCache) Exists

func (tc *TieredCache) Exists(ctx context.Context, key string) (bool, error)

Exists checks if a key exists in either L1 or L2 cache

func (*TieredCache) Get

func (tc *TieredCache) Get(ctx context.Context, key string, dest interface{}) (bool, error)

Get retrieves a value from the cache, checking L1 first, then L2

func (*TieredCache) GetL1Cache

func (tc *TieredCache) GetL1Cache() Cache

GetL1Cache returns the L1 (fast) cache instance

func (*TieredCache) GetL2Cache

func (tc *TieredCache) GetL2Cache() Cache

GetL2Cache returns the L2 (persistent) cache instance

func (*TieredCache) GetMulti

func (tc *TieredCache) GetMulti(ctx context.Context, keys []string) (map[string]interface{}, error)

GetMulti retrieves multiple values from the cache

func (*TieredCache) GetStats

func (tc *TieredCache) GetStats() Stats

GetStats returns combined statistics from both cache levels

func (*TieredCache) GetTTL

func (tc *TieredCache) GetTTL(ctx context.Context, key string) (time.Duration, error)

GetTTL returns the remaining TTL for a key from L2 cache

func (*TieredCache) GetTieredStats

func (tc *TieredCache) GetTieredStats() map[string]Stats

GetTieredStats returns detailed statistics for each cache level

func (*TieredCache) InvalidateL1

func (tc *TieredCache) InvalidateL1(ctx context.Context, key string) error

InvalidateL1 removes a key from L1 cache while keeping it in L2

func (*TieredCache) Set

func (tc *TieredCache) Set(ctx context.Context, key string, value interface{}, ttl time.Duration) error

Set stores a value in both L1 and L2 caches

func (*TieredCache) SetMulti

func (tc *TieredCache) SetMulti(ctx context.Context, items map[string]interface{}, ttl time.Duration) error

SetMulti stores multiple values in both L1 and L2 caches

func (*TieredCache) SetTTL

func (tc *TieredCache) SetTTL(ctx context.Context, key string, ttl time.Duration) error

SetTTL updates the TTL for an existing key in both caches

func (*TieredCache) WarmupL1

func (tc *TieredCache) WarmupL1(ctx context.Context, keys []string) error

WarmupL1 preloads L1 cache with values from L2 cache

func (*TieredCache) WithEventHandler

func (tc *TieredCache) WithEventHandler(handler EventHandler) *TieredCache

WithEventHandler sets the event handler for cache events

Jump to

Keyboard shortcuts

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