cache

package
v1.7.2 Latest Latest
Warning

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

Go to latest
Published: Dec 22, 2025 License: BSD-3-Clause Imports: 11 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"`
	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 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.

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 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