cache

package
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Aug 18, 2025 License: Apache-2.0 Imports: 8 Imported by: 0

README

Cache Package

A flexible caching solution for Go applications that supports both in-memory and Redis backends. Switch between drivers with just an environment variable - no code changes required.

Features

  • Multiple Drivers: Built-in memory cache and Redis support
  • Zero Code Changes: Switch drivers via environment variables
  • Environment-First: Follows Beaver Kit's BEAVER_ prefix convention
  • Connection Pooling: Optimized Redis connection management
  • TTL Support: Set expiration times for cached values
  • Namespace Isolation: Separate cache spaces with prefixes
  • Health Checks: Built-in health monitoring
  • Thread-Safe: Safe for concurrent use

Installation

go get github.com/gobeaver/beaver-kit/cache

Quick Start

Using Environment Variables
# For in-memory cache (default)
export BEAVER_CACHE_DRIVER=memory

# For Redis
export BEAVER_CACHE_DRIVER=redis
export BEAVER_CACHE_HOST=localhost
export BEAVER_CACHE_PORT=6379
package main

import (
    "context"
    "log"
    "time"
    
    "github.com/gobeaver/beaver-kit/cache"
)

func main() {
    // Initialize from environment
    if err := cache.Init(); err != nil {
        log.Fatal(err)
    }
    
    ctx := context.Background()
    
    // Store a value
    err := cache.Set(ctx, "user:123", []byte("John Doe"), 5*time.Minute)
    if err != nil {
        log.Fatal(err)
    }
    
    // Retrieve a value
    data, err := cache.Get(ctx, "user:123")
    if err != nil {
        log.Fatal(err)
    }
    
    log.Printf("User: %s", string(data))
}
Using Specific Configuration
// In-memory cache
memCache, err := cache.New(cache.Config{
    Driver:    "memory",
    MaxKeys:   10000,
    MaxSize:   100 * 1024 * 1024, // 100MB
    DefaultTTL: 10 * time.Minute,
})

// Redis cache
redisCache, err := cache.New(cache.Config{
    Driver:   "redis",
    Host:     "localhost",
    Port:     "6379",
    Database: 0,
    KeyPrefix: "myapp:",
})

Configuration

Environment Variables
Variable Description Default
BEAVER_CACHE_DRIVER Cache driver: memory or redis memory
BEAVER_CACHE_HOST Redis host localhost
BEAVER_CACHE_PORT Redis port 6379
BEAVER_CACHE_PASSWORD Redis password -
BEAVER_CACHE_DATABASE Redis database number 0
BEAVER_CACHE_URL Redis URL (overrides host/port) -
BEAVER_CACHE_KEY_PREFIX Prefix for all keys -
BEAVER_CACHE_NAMESPACE Namespace for isolation -
Memory Cache Settings
BEAVER_CACHE_MAX_SIZE Max memory in bytes 0 (unlimited)
BEAVER_CACHE_MAX_KEYS Max number of keys 0 (unlimited)
BEAVER_CACHE_DEFAULT_TTL Default TTL (e.g., "5m", "1h") 0 (no expiry)
BEAVER_CACHE_CLEANUP_INTERVAL Cleanup interval 1m
Redis Connection Pool
BEAVER_CACHE_POOL_SIZE Connection pool size 10
BEAVER_CACHE_MIN_IDLE_CONNS Min idle connections 2
BEAVER_CACHE_MAX_IDLE_CONNS Max idle connections 5
BEAVER_CACHE_MAX_RETRIES Max retry attempts 3
TLS Settings
BEAVER_CACHE_USE_TLS Enable TLS false
BEAVER_CACHE_CERT_FILE TLS certificate file -
BEAVER_CACHE_KEY_FILE TLS key file -
BEAVER_CACHE_CA_FILE TLS CA file -

Driver Features

Memory Driver
  • Zero dependencies
  • Fast for small datasets
  • Automatic cleanup of expired items
  • Memory and key count limits
  • Best for: Development, small apps, temporary data
Redis Driver
  • Distributed caching across servers
  • Persistence options
  • Pub/sub capabilities
  • Clustering support
  • Best for: Production, microservices, shared cache

API Reference

Core Operations
// Get retrieves a value by key
Get(ctx context.Context, key string) ([]byte, error)

// Set stores a value with optional TTL
Set(ctx context.Context, key string, value []byte, ttl time.Duration) error

// Delete removes a key
Delete(ctx context.Context, key string) error

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

// Clear removes all keys (with prefix if configured)
Clear(ctx context.Context) error

// Ping checks if cache is reachable
Ping(ctx context.Context) error
Global Functions

All operations are available as package-level functions after initialization:

cache.Init()
cache.Set(ctx, "key", data, ttl)
cache.Get(ctx, "key")
cache.Delete(ctx, "key")
cache.Exists(ctx, "key")
cache.Clear(ctx)
cache.IsHealthy()

Examples

Switching Drivers Without Code Changes
// Your code remains the same
func saveUserSession(userID string, session []byte) error {
    return cache.Set(context.Background(), 
        fmt.Sprintf("session:%s", userID), 
        session, 
        30*time.Minute)
}

// Switch driver via environment
// Development: BEAVER_CACHE_DRIVER=memory
// Production:  BEAVER_CACHE_DRIVER=redis
Using Namespaces
// Separate cache spaces for different services
userCache, _ := cache.New(cache.Config{
    Driver:    "redis",
    Namespace: "users",
})

orderCache, _ := cache.New(cache.Config{
    Driver:    "redis",
    Namespace: "orders",
})

// Keys are automatically prefixed: "users:123", "orders:456"
Connection URL
// Use Redis URL for cloud providers
cache.Init(cache.Config{
    Driver: "redis",
    URL:    "redis://user:pass@redis.example.com:6379/0",
})
Health Monitoring
// Check cache health
if !cache.IsHealthy() {
    log.Println("Cache is down!")
}

// Or with context
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()

if err := cache.Health(ctx); err != nil {
    log.Printf("Cache unhealthy: %v", err)
}

Testing

The package includes comprehensive tests for both drivers:

# Run all tests
go test ./cache/...

# Test with Redis (requires running Redis)
docker run -d -p 6379:6379 redis:alpine
go test ./cache/...

Performance Considerations

Memory Driver
  • O(1) operations for get/set/delete
  • Cleanup runs periodically (configurable)
  • Best for <100MB of data
  • Consider MaxKeys to prevent unbounded growth
Redis Driver
  • Network latency considerations
  • Use connection pooling settings
  • Enable pipelining for batch operations
  • Consider Redis persistence settings

Error Handling

data, err := cache.Get(ctx, "key")
if err != nil {
    if errors.Is(err, cache.ErrKeyNotFound) {
        // Key doesn't exist
    } else {
        // Other error (network, etc.)
    }
}

Thread Safety

Both drivers are safe for concurrent use. The memory driver uses fine-grained locking, while Redis handles concurrency at the server level.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrNotInitialized = errors.New("cache not initialized")
	ErrInvalidDriver  = errors.New("invalid cache driver")
	ErrInvalidConfig  = errors.New("invalid cache configuration")
	ErrKeyNotFound    = errors.New("key not found")
	ErrInvalidTTL     = errors.New("invalid TTL value")
)

Common errors

Functions

func Clear

func Clear(ctx context.Context) error

Clear removes all keys from the global cache

func Delete

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

Delete removes a key from the global cache

func Exists

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

Exists checks if a key exists in the global cache

func Get

func Get(ctx context.Context, key string) ([]byte, error)

Get retrieves a value by key from the global cache

func Health

func Health(ctx context.Context) error

Health is an alias for Ping

func Init

func Init(configs ...Config) error

Init initializes the global cache instance with optional config

func InitFromEnv

func InitFromEnv() error

InitFromEnv is an alias for Init with no arguments

func IsHealthy

func IsHealthy() bool

IsHealthy returns true if the cache is reachable

func MustInit

func MustInit(configs ...Config)

MustInit initializes the cache and panics on error

func Ping

func Ping(ctx context.Context) error

Ping checks if the global cache is reachable

func Reset

func Reset()

Reset clears the global instance (for testing)

func Set

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

Set stores a value with optional TTL in the global cache

func Shutdown

func Shutdown(ctx context.Context) error

Shutdown gracefully closes cache connections

Types

type Builder

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

Builder provides a way to create cache instances with custom prefixes

func WithPrefix

func WithPrefix(prefix string) *Builder

WithPrefix creates a new Builder with the specified prefix

func (*Builder) Init

func (b *Builder) Init() error

Init initializes the global cache instance using the builder's prefix

func (*Builder) New

func (b *Builder) New() (Cache, error)

New creates a new cache instance using the builder's prefix

type Cache

type Cache interface {
	// Get retrieves a value by key
	Get(ctx context.Context, key string) ([]byte, error)

	// Set stores a value with optional TTL
	Set(ctx context.Context, key string, value []byte, ttl time.Duration) error

	// Delete removes a key
	Delete(ctx context.Context, key string) error

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

	// Clear removes all keys
	Clear(ctx context.Context) error

	// Close closes the cache connection
	Close() error

	// Ping checks if cache is reachable
	Ping(ctx context.Context) error
}

Cache defines the interface for cache implementations

func Default

func Default() Cache

Default returns the global cache instance

func New

func New(cfg Config) (Cache, error)

New creates a new cache instance with given config

func NewFromEnv

func NewFromEnv() (Cache, error)

NewFromEnv creates cache instance from environment variables

type Config

type Config struct {
	// Driver specifies cache backend: "memory" or "redis"
	Driver string `env:"CACHE_DRIVER,default:memory"`

	// Redis specific settings
	Host     string `env:"CACHE_HOST,default:localhost"`
	Port     string `env:"CACHE_PORT,default:6379"`
	Password string `env:"CACHE_PASSWORD"`
	Database int    `env:"CACHE_DATABASE,default:0"`

	// Connection URL (overrides host/port/password)
	URL string `env:"CACHE_URL"`

	// Connection pool settings
	MaxRetries      int `env:"CACHE_MAX_RETRIES,default:3"`
	PoolSize        int `env:"CACHE_POOL_SIZE,default:10"`
	MinIdleConns    int `env:"CACHE_MIN_IDLE_CONNS,default:2"`
	MaxIdleConns    int `env:"CACHE_MAX_IDLE_CONNS,default:5"`
	ConnMaxLifetime int `env:"CACHE_CONN_MAX_LIFETIME,default:0"`  // seconds
	ConnMaxIdleTime int `env:"CACHE_CONN_MAX_IDLE_TIME,default:0"` // seconds

	// Memory cache specific
	MaxSize         int64  `env:"CACHE_MAX_SIZE,default:0"`          // max memory in bytes
	MaxKeys         int    `env:"CACHE_MAX_KEYS,default:0"`          // max number of keys
	DefaultTTL      string `env:"CACHE_DEFAULT_TTL,default:0"`       // default TTL as duration string
	CleanupInterval string `env:"CACHE_CLEANUP_INTERVAL,default:1m"` // cleanup interval as duration string

	// TLS settings for Redis
	UseTLS   bool   `env:"CACHE_USE_TLS,default:false"`
	CertFile string `env:"CACHE_CERT_FILE"`
	KeyFile  string `env:"CACHE_KEY_FILE"`
	CAFile   string `env:"CACHE_CA_FILE"`

	// Common settings
	KeyPrefix string `env:"CACHE_KEY_PREFIX"` // prefix for all keys
	Namespace string `env:"CACHE_NAMESPACE"`  // namespace for isolation
}

Config holds cache configuration

func GetConfig

func GetConfig() (*Config, error)

GetConfig loads configuration from environment variables

func (Config) ParsedCleanupInterval

func (c Config) ParsedCleanupInterval() time.Duration

ParsedCleanupInterval returns the cleanup interval as a time.Duration

func (Config) ParsedDefaultTTL

func (c Config) ParsedDefaultTTL() time.Duration

ParsedDefaultTTL returns the default TTL as a time.Duration

Directories

Path Synopsis
driver

Jump to

Keyboard shortcuts

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