cache

package
v0.0.0-...-cd2fe80 Latest Latest
Warning

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

Go to latest
Published: Oct 14, 2025 License: MIT Imports: 13 Imported by: 0

README

Cache Package

This package provides a caching interface with multiple backend implementations and distributed locking capabilities.

Features

  • Pluggable backend implementations (Redis, in-memory)
  • Key-value cache operations with TTL support
  • Thread-safe and concurrent access

Metrics

The cache package exposes the following Prometheus metrics:

Metric Name Type Description Labels
lab_cache_requests_total Counter Total number of cache requests operation ("get", "set", "delete"), status ("hit", "miss", "error", "ok")
lab_cache_operation_duration_seconds Histogram Duration of cache operations in seconds operation ("get", "set", "delete")
lab_cache_items Gauge Current number of items in the cache none
lab_cache_hits_total Counter Total number of cache hits none
lab_cache_misses_total Counter Total number of cache misses none

These metrics are automatically collected for both memory and Redis cache implementations.

Cache Interface

The primary interface for cache operations:

// Client is a cache client
type Client interface {
	// Get gets a value from the cache
	Get(key string) ([]byte, error)

	// Set sets a value in the cache
	Set(key string, value []byte, ttl time.Duration) error

	// Delete deletes a value from the cache
	Delete(key string) error

	// Stop gracefully stops the cache
	Stop() error
}

Implementations

Memory Cache

The in-memory implementation provides a simple, single-process cache with lock support.

Redis Cache

The Redis implementation uses Redis for both caching and distributed locks, providing cross-process and cross-server coordination.

For distributed locking, the Redis implementation uses:

  • SET NX with expiration for acquiring locks
  • Lua script for atomic unlocking, ensuring only the owner can release the lock

Usage Examples

Basic Cache Operations
// Create a metrics service
logger := logrus.New()
metricsSvc := metrics.NewMetricsService("lab", logger)

// Create a cache (memory or Redis)
config := cache.Config{
    Type: cache.CacheTypeMemory,
    Config: map[string]interface{}{
        "defaultTTL": "5m",
    },
}
cacheClient, err := cache.New(&config, metricsSvc)
if err != nil {
    log.Fatalf("Error creating cache: %v", err)
}
defer cacheClient.Stop()

// Set a value with a TTL
err = cacheClient.Set("my-key", []byte("hello world"), 30*time.Second)
if err != nil {
    log.Fatalf("Error setting value: %v", err)
}

// Get a value
value, err := cacheClient.Get("my-key")
if err != nil {
    log.Fatalf("Error getting value: %v", err)
}
fmt.Printf("Value: %s\n", value)

// Delete a value
err = cacheClient.Delete("my-key")
if err != nil {
    log.Fatalf("Error deleting value: %v", err)
}

Testing

This package includes comprehensive tests for both the memory and Redis implementations, including tests for distributed locking and leader election.

The Redis tests use testcontainers-go to spin up Redis containers for integration testing.

Run tests with: go test -v

Documentation

Index

Constants

View Source
const (
	StatusMiss  = "miss"
	StatusError = "error"
	StatusHit   = "hit"
	StatusOK    = "ok"
)

Status constants for metrics

View Source
const (
	ErrCacheMissMsg = "key not found in cache"
)

Error message constants

Variables

View Source
var ErrCacheMiss = errors.New(ErrCacheMissMsg)

Error returned when a key is not found in the cache

Functions

func GenerateToken

func GenerateToken() (string, error)

GenerateToken generates a random token for lock identification

Types

type CacheType

type CacheType string
const (
	CacheTypeRedis  CacheType = "redis"
	CacheTypeMemory CacheType = "memory"
)

type Client

type Client interface {
	// Get gets a value from the cache
	Get(key string) ([]byte, error)

	// Set sets a value in the cache
	Set(key string, value []byte, ttl time.Duration) error

	// SetNX sets a value in the cache only if the key doesn't exist
	// Returns true if the value was set, false if it already exists
	SetNX(key string, value []byte, ttl time.Duration) (bool, error)

	// SetIfMatch sets a value in the cache only if the current value matches the expected value
	// Returns true if the value was set, false if the current value doesn't match
	SetIfMatch(key string, value []byte, expected []byte, ttl time.Duration) (bool, error)

	// Delete deletes a value from the cache
	Delete(key string) error

	// Stop gracefully stops the cache
	Stop() error
}

Client is a cache client

func New

func New(config *Config, metricsSvc *metrics.Metrics) (Client, error)

New creates a new cache based on the config

type Config

type Config struct {
	Type   CacheType `yaml:"type"` // "redis" or "memory"
	Config map[string]any
}

Config contains configuration for caches

func (*Config) Validate

func (c *Config) Validate() error

type Memory

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

Memory implements an in-memory cache

func NewMemory

func NewMemory(config MemoryConfig, metricsSvc *metrics.Metrics) *Memory

NewMemory creates a new memory cache

func (*Memory) Delete

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

Delete deletes a value from the cache

func (*Memory) Get

func (c *Memory) Get(key string) ([]byte, error)

Get gets a value from the cache

func (*Memory) Set

func (c *Memory) Set(key string, value []byte, ttl time.Duration) error

Set sets a value in the cache

func (*Memory) SetIfMatch

func (c *Memory) SetIfMatch(key string, value []byte, expected []byte, ttl time.Duration) (bool, error)

SetIfMatch sets a value in the cache only if the current value matches expected (atomic operation)

func (*Memory) SetNX

func (c *Memory) SetNX(key string, value []byte, ttl time.Duration) (bool, error)

SetNX sets a value in the cache only if the key doesn't exist (atomic operation)

func (*Memory) Stop

func (c *Memory) Stop() error

Stop gracefully stops the cache

type MemoryConfig

type MemoryConfig struct {
	DefaultTTL time.Duration `yaml:"defaultTTL"`
}

MemoryConfig contains configuration for memory cache

type Redis

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

Redis is a Redis-backed cache implementation

func NewRedis

func NewRedis(config RedisConfig, metricsSvc *metrics.Metrics) (*Redis, error)

NewRedis creates a new Redis cache

func (*Redis) Delete

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

Delete removes a value from Redis

func (*Redis) Get

func (r *Redis) Get(key string) ([]byte, error)

Get retrieves a value from Redis

func (*Redis) Set

func (r *Redis) Set(key string, value []byte, ttl time.Duration) error

Set stores a value in Redis with TTL

func (*Redis) SetIfMatch

func (r *Redis) SetIfMatch(key string, value []byte, expected []byte, ttl time.Duration) (bool, error)

SetIfMatch sets a value in Redis only if the current value matches expected (atomic operation)

func (*Redis) SetNX

func (r *Redis) SetNX(key string, value []byte, ttl time.Duration) (bool, error)

SetNX sets a value in Redis only if the key doesn't exist (atomic operation)

func (*Redis) Stop

func (r *Redis) Stop() error

Stop closes the Redis connection and stops background goroutines

type RedisConfig

type RedisConfig struct {
	URL        string        `yaml:"url"`        // Redis connection URL
	DefaultTTL time.Duration `yaml:"defaultTTL"` // Default TTL for cache items
}

RedisConfig contains configuration for Redis cache

Jump to

Keyboard shortcuts

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