gencache

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: May 18, 2025 License: MIT Imports: 17 Imported by: 1

README

GenCache

Go Report Card GoDoc License Go Version Build Status Coverage Release

A high-performance, generic caching library with support for multiple storage backends, batch operations, compression, and object pooling.

Summary

GenCache is a robust, thread-safe caching library designed for high-performance applications. It provides a unified interface for caching with support for in-memory and file-based storage, batch operations, compression, and object pooling. Built with Go's generics, it offers type safety and flexibility for various use cases.

Features

  • Generic Caching: Type-safe caching with Go generics.
  • Multiple Storage Backends:
    • In-memory store for fastest access.
    • File-based store for persistence.
  • Batch Operations: Efficient bulk processing for high throughput.
  • Compression Support: Memory optimization with configurable compression levels.
  • Object Pooling: Reduced GC pressure and improved performance.
  • Unified Metrics and Monitoring: Track hit/miss rates, memory usage, and operation latencies. See Metrics Guide for detailed usage.
  • Resource Coordination and Cleanup: Automatic cleanup of expired items and resources.
  • Configurable Components: Tune cleanup intervals, size limits, and compression settings.
  • TTL (Time-To-Live) Support: Automatic expiration of cached items.
  • Thread-Safe Operations: Concurrent access without data races.

Installation

go get github.com/gozephyr/gencache

Basic Usage

Memory Store Example
import (
    "context"
    "time"
    "github.com/gozephyr/gencache"
    "github.com/gozephyr/gencache/store"
    "github.com/gozephyr/gencache/ttl"
)

func main() {
    ctx := context.Background()

    // Create a memory store
    memStore, err := store.NewMemoryStore[string, string](ctx)
    if err != nil {
        // Handle error
    }
    defer memStore.Close(ctx)

    // Create a cache with memory store
    cache := gencache.New[string, string](
        gencache.WithStore[string, string](memStore),
        gencache.WithTTLConfig[string, string](ttl.DefaultConfig()),
    )
    defer cache.Close()

    // Set and get values
    err = cache.Set("key", "value", time.Minute)
    if err != nil {
        // Handle error
    }

    value, err := cache.Get("key")
    if err != nil {
        // Handle error
    }
}
Memory Store Capabilities
  • Fastest access with in-memory storage.
  • Configurable size limits.
  • Automatic cleanup of expired items.
  • Thread-safe operations.
  • Memory usage tracking.
Memory Store Performance
  1. Memory Usage:

    • Proportional to number of items.
    • Each item stores key, value, and metadata.
    • Overhead: ~100 bytes per item.
  2. CPU Usage:

    • Minimal overhead for operations.
    • Fast access and updates.
    • Efficient cleanup of expired items.
File Store
import (
    "context"
    "time"
    "github.com/gozephyr/gencache"
    "github.com/gozephyr/gencache/store"
    "github.com/gozephyr/gencache/ttl"
)

func main() {
    ctx := context.Background()

    // Create a file store
    fileStore, err := store.NewFileStore[string, string](ctx, &store.FileConfig{
        Directory:          "/tmp/cache",
        FileExtension:      ".cache",
        CompressionEnabled: true,
        CompressionLevel:   6,
        CleanupInterval:    time.Hour,
    })
    if err != nil {
        // Handle error
    }
    defer fileStore.Close(ctx)

    // Create a cache with file store
    cache := gencache.New[string, string](
        gencache.WithStore[string, string](fileStore),
        gencache.WithTTLConfig[string, string](ttl.DefaultConfig()),
    )
    defer cache.Close()

    // Set and get values
    err = cache.Set("key", "value", time.Minute)
    if err != nil {
        // Handle error
    }

    value, err := cache.Get("key")
    if err != nil {
        // Handle error
    }
}

Advanced Features

Batch Operations
import (
    "context"
    "time"
    "github.com/gozephyr/gencache"
)

func main() {
    ctx := context.Background()

    // Create a cache with batch operations
    cache := gencache.New[string, string](
        gencache.WithBatchConfig[string, string](gencache.BatchConfig{
            MaxBatchSize:     1000,
            OperationTimeout: 5 * time.Second,
            MaxConcurrent:    10,
        }),
    )
    defer cache.Close()

    // Create batch cache
    batchCache := gencache.NewBatchCache(cache, gencache.DefaultBatchConfig())

    // Batch get operation
    values := batchCache.GetMany(ctx, []string{"key1", "key2", "key3"})

    // Batch set operation
    err := batchCache.SetMany(ctx, map[string]string{
        "key1": "value1",
        "key2": "value2",
        "key3": "value3",
    }, time.Minute)
    if err != nil {
        // Handle error
    }
}
Object Pooling
import (
    "context"
    "time"
    "github.com/gozephyr/gencache"
)

type MyStruct struct {
    ID   int
    Name string
}

func main() {
    ctx := context.Background()

    // Create a cache with object pooling
    cache := gencache.New[string, *MyStruct](
        gencache.WithPoolConfig[string, *MyStruct](gencache.PoolConfig{
            MaxSize:       1000,
            MinSize:       10,
            CleanupPeriod: 5 * time.Minute,
            MaxIdleTime:   10 * time.Minute,
        }),
    )
    defer cache.Close()

    // Create pooled cache
    pooledCache := gencache.NewPooledCache(cache, gencache.DefaultPoolConfig())

    // Use pooled objects
    obj := &MyStruct{ID: 1, Name: "test"}
    err := pooledCache.Set("key", obj, time.Minute)
    if err != nil {
        // Handle error
    }

    value, err := pooledCache.Get("key")
    if err != nil {
        // Handle error
    }
}

Storage Backends

Memory Store
  • Fastest access with in-memory storage.
  • Configurable size limits.
  • Automatic cleanup of expired items.
  • Thread-safe operations.
  • Memory usage tracking.
File Store Overview
  • Persistent storage using filesystem.
  • Configurable directory and file extension.
  • Automatic cleanup of expired files.
  • Compression support.
  • Thread-safe operations.
  • File-based locking.

Performance Considerations

Memory Store Metrics
  1. Memory Usage:

    • Proportional to number of items.
    • Each item stores key, value, and metadata.
    • Overhead: ~100 bytes per item.
  2. CPU Usage:

    • Minimal overhead for operations.
    • Fast access and updates.
    • Efficient cleanup of expired items.
File Store Performance
  1. Memory Usage:

    • Minimal memory overhead.
    • Values stored on disk.
    • Memory usage for file handles and buffers.
  2. CPU Usage:

    • File I/O operations.
    • Compression/decompression overhead.
    • Periodic cleanup of expired files.
  3. Disk Usage:

    • Proportional to stored data size.
    • Additional space for metadata.
    • Compression can reduce disk usage.

Benchmarks

  • Memory Store: ~100,000 operations per second for small values.
  • File Store: ~10,000 operations per second for small values, depending on disk speed and compression settings.

Best Practices

  1. Storage Selection:

    • Use memory store for fastest access.
    • Use file store for persistence.
    • Consider data size and access patterns.
  2. Configuration:

    • Tune cleanup intervals.
    • Set appropriate size limits.
    • Configure compression settings.
  3. Error Handling:

    • Handle storage errors.
    • Implement retry logic.
    • Monitor error rates.
  4. Monitoring:

    • Track hit/miss rates.
    • Monitor memory usage.
    • Watch disk usage (file store).
    • Track operation latencies.

Error Handling

The library provides comprehensive error handling:

if err := cache.Set("key", "value", time.Minute); err != nil {
    switch {
    case errors.Is(err, errors.ErrKeyNotFound):
        // Handle key not found
    case errors.Is(err, errors.ErrCapacityLimit):
        // Handle capacity limit
    case errors.Is(err, errors.ErrContextCanceled):
        // Handle context cancellation
    default:
        // Handle other errors
    }
}

Metrics Example

For detailed metrics usage and examples, please refer to the Metrics Guide.

Eviction Policies

GenCache supports pluggable cache eviction policies via the policy package. You can choose from several built-in policies:

  • LRU (Least Recently Used): Evicts the least recently accessed items first.
  • LFU (Least Frequently Used): Evicts the least frequently accessed items first.
  • FIFO (First In First Out): Evicts the oldest items first.
Policy Package

The policy package provides a flexible framework for implementing custom cache eviction policies. It defines a generic Policy interface that can be implemented for any key-value type combination.

Policy Interface
type Policy[K comparable, V any] interface {
    // OnGet is called when an item is retrieved from the cache
    OnGet(key K, value V)

    // OnSet is called when an item is added to the cache
    OnSet(key K, value V, ttl time.Duration)

    // OnDelete is called when an item is removed from the cache
    OnDelete(key K)

    // OnClear is called when the cache is cleared
    OnClear()

    // Evict returns the next key to be evicted from the cache
    Evict() (K, bool)

    // Size returns the number of items in the policy
    Size() int

    // Capacity returns the maximum number of items the policy can hold
    Capacity() int
}
Entry Metadata

Each cache entry maintains metadata to help with policy decisions:

type Entry[V any] struct {
    Value       V         // The cached value
    Expires     time.Time // When the entry expires
    CreatedAt   time.Time // When the entry was created
    LastAccess  time.Time // When the entry was last accessed
    AccessCount int64     // Number of times the entry was accessed
}

Documentation

Overview

Package gencache provides a generic caching mechanism

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type BatchCache

type BatchCache[K comparable, V any] interface {
	Cache[K, V]

	// GetMany retrieves multiple values from the cache
	GetMany(ctx context.Context, keys []K) map[K]V

	// SetMany stores multiple values in the cache
	SetMany(ctx context.Context, entries map[K]V, ttl time.Duration) error

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

	// GetBatchMetrics returns the current batch operation metrics
	GetBatchMetrics() *BatchMetrics

	// ResetBatchMetrics resets the batch operation metrics
	ResetBatchMetrics()
}

BatchCache extends Cache with batch operations

func NewBatchCache

func NewBatchCache[K comparable, V any](c Cache[K, V], config BatchConfig) BatchCache[K, V]

NewBatchCache creates a new cache with batch operations

type BatchConfig

type BatchConfig struct {
	MaxBatchSize     int
	OperationTimeout time.Duration
	MaxConcurrent    int
	TTLConfig        ttl.Config
}

BatchConfig represents configuration for batch operations

func DefaultBatchConfig

func DefaultBatchConfig() BatchConfig

DefaultBatchConfig returns the default batch configuration

type BatchMetrics

type BatchMetrics struct {
	TotalOperations atomic.Int64
	TotalItems      atomic.Int64
	SuccessCount    atomic.Int64
	ErrorCount      atomic.Int64
	TimeoutCount    atomic.Int64
	LastOperation   atomic.Value // time.Time
}

BatchMetrics represents metrics for batch operations

type BatchResult

type BatchResult[K comparable, V any] struct {
	Key   K
	Value V
	Error error
}

BatchResult represents the result of a batch operation

type BatchResultPool

type BatchResultPool[K comparable, V any] struct {
	// contains filtered or unexported fields
}

BatchResultPool provides a pool of batch results

func NewBatchResultPool

func NewBatchResultPool[K comparable, V any]() *BatchResultPool[K, V]

NewBatchResultPool creates a new pool of batch results

func (*BatchResultPool[K, V]) Get

func (p *BatchResultPool[K, V]) Get() BatchResult[K, V]

Get retrieves a batch result from the pool

func (*BatchResultPool[K, V]) Put

func (p *BatchResultPool[K, V]) Put(result BatchResult[K, V])

Put returns a batch result to the pool

type Cache

type Cache[K comparable, V any] interface {
	// Get retrieves a value from the cache
	Get(key K) (V, error)

	// GetWithContext retrieves a value from the cache with context
	GetWithContext(ctx context.Context, key K) (V, error)

	// Set stores a value in the cache with TTL
	Set(key K, value V, ttl time.Duration) error

	// SetWithContext stores a value in the cache with context and TTL
	SetWithContext(ctx context.Context, key K, value V, ttl time.Duration) error

	// Delete removes a value from the cache
	Delete(key K) error

	// DeleteWithContext removes a value from the cache with context
	DeleteWithContext(ctx context.Context, key K) error

	// Clear removes all values from the cache
	Clear() error

	// ClearWithContext removes all values from the cache with context
	ClearWithContext(ctx context.Context) error

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

	// Stats returns the current cache statistics
	Stats() *Stats

	// OnEvent registers a callback function for cache events
	OnEvent(callback CacheCallback[K, V])
}

Cache defines the interface for a generic cache

func New

func New[K comparable, V any](opts ...Option[K, V]) Cache[K, V]

New creates a new cache with the given options

type CacheCallback

type CacheCallback[K comparable, V any] func(CacheEvent[K, V])

CacheCallback is a function that handles cache events

type CacheEvent

type CacheEvent[K comparable, V any] struct {
	Type      CacheEventType
	Key       K
	Value     V
	Timestamp time.Time
}

CacheEvent represents an event that occurred in the cache

type CacheEventType

type CacheEventType int

CacheEventType represents the type of cache event

const (
	EventTypeSet CacheEventType = iota
	EventTypeGet
	EventTypeDelete
	EventTypeEviction
	EventTypeExpiration
)

type CacheWithStats

type CacheWithStats[K comparable, V any] interface {
	Cache[K, V]

	// GetStats returns the current cache statistics
	GetStats() StatsSnapshot

	// ResetStats resets the cache statistics
	ResetStats()
}

CacheWithStats extends Cache with statistics tracking

type Client

type Client interface {
	Close() error
}

Client interface for underlying storage

type CompressedCache

type CompressedCache[K comparable, V any] interface {
	Cache[K, V]

	// GetCompressionStats returns the current compression statistics
	GetCompressionStats() *CompressionStats

	// ResetCompressionStats resets the compression statistics
	ResetCompressionStats()

	// SetCompressionConfig updates the compression configuration
	SetCompressionConfig(config CompressionConfig)

	// GetCompressionConfig returns the current compression configuration
	GetCompressionConfig() CompressionConfig

	// OnEvent registers a callback for cache events
	OnEvent(cb CacheCallback[K, V])
}

CompressedCache extends Cache with compression

func NewCompressedCache

func NewCompressedCache[K comparable, V any](c Cache[K, any], config CompressionConfig) CompressedCache[K, V]

NewCompressedCache creates a new cache with compression

type CompressedValue

type CompressedValue struct {
	Data      []byte
	Algorithm CompressionAlgorithm
}

CompressedValue is a wrapper for compressed data Used internally to mark values as compressed and to store the compressed bytes and algorithm so that Get can decompress them.

type CompressionAlgorithm

type CompressionAlgorithm int

CompressionAlgorithm represents the compression algorithm to use

const (
	// GzipCompression uses gzip compression
	GzipCompression CompressionAlgorithm = iota
	// ZlibCompression uses zlib compression
	ZlibCompression
	// LZWCompression uses LZW compression
	LZWCompression
)

type CompressionConfig

type CompressionConfig struct {
	Algorithm     CompressionAlgorithm
	Level         int
	MinSize       int
	MaxSize       int
	StatsEnabled  bool
	StatsInterval time.Duration
}

CompressionConfig represents configuration for compression

func DefaultCompressionConfig

func DefaultCompressionConfig() CompressionConfig

DefaultCompressionConfig returns the default compression configuration

type CompressionStats

type CompressionStats struct {
	TotalCompressed     atomic.Int64
	TotalDecompressed   atomic.Int64
	TotalBytesIn        atomic.Int64
	TotalBytesOut       atomic.Int64
	CompressionRatio    atomic.Value // float64
	LastCompressionTime atomic.Value // time.Time
	LastStatsReset      atomic.Value // time.Time
}

CompressionStats represents statistics for compression

type Entry

type Entry[V any] struct {
	Value       V         `json:"value"`
	Expires     time.Time `json:"expires"`
	CreatedAt   time.Time `json:"createdAt"`
	LastAccess  time.Time `json:"lastAccess"`
	AccessCount int64     `json:"accessCount"`
}

Entry represents a cached value with metadata

type EntryPool

type EntryPool[V any] struct {
	// contains filtered or unexported fields
}

EntryPool provides a pool of cache entries

func NewEntryPool

func NewEntryPool[V any]() *EntryPool[V]

NewEntryPool creates a new pool of cache entries

func (*EntryPool[V]) Get

func (p *EntryPool[V]) Get() Entry[V]

Get retrieves an entry from the pool

func (*EntryPool[V]) Put

func (p *EntryPool[V]) Put(entry Entry[V])

Put returns an entry to the pool

type MetricsConfig

type MetricsConfig struct {
	// ExporterType specifies the type of metrics exporter to use
	ExporterType metrics.ExporterType
	// CacheName is used as a label for Prometheus metrics
	CacheName string
	// Labels are additional labels to be added to metrics
	Labels map[string]string
}

MetricsConfig defines the configuration for metrics

type ObjectPool

type ObjectPool[T any] struct {
	// contains filtered or unexported fields
}

ObjectPool provides a pool of reusable objects

func NewObjectPool

func NewObjectPool[T any](newFunc func() T) *ObjectPool[T]

NewObjectPool creates a new object pool

func (*ObjectPool[T]) Get

func (p *ObjectPool[T]) Get() T

Get retrieves an object from the pool

func (*ObjectPool[T]) Put

func (p *ObjectPool[T]) Put(x T)

Put returns an object to the pool

type Option

type Option[K comparable, V any] func(*Options[K, V])

Option is a function that configures cache options

func WithBatchConfig

func WithBatchConfig[K comparable, V any](config BatchConfig) Option[K, V]

WithBatchConfig sets the batch operation configuration

func WithCleanupInterval

func WithCleanupInterval[K comparable, V any](interval time.Duration) Option[K, V]

WithCleanupInterval sets the cleanup interval for the cache

func WithCompressionConfig

func WithCompressionConfig[K comparable, V any](config CompressionConfig) Option[K, V]

WithCompressionConfig sets the compression configuration

func WithMaxMemory

func WithMaxMemory[K comparable, V any](maxMemory int64) Option[K, V]

WithMaxMemory sets the maximum memory usage in bytes

func WithMaxSize

func WithMaxSize[K comparable, V any](size int) Option[K, V]

WithMaxSize sets the maximum size of the cache

func WithMemoryTracking

func WithMemoryTracking[K comparable, V any](enable bool) Option[K, V]

WithMemoryTracking enables memory usage tracking

func WithMetricsConfig

func WithMetricsConfig[K comparable, V any](config MetricsConfig) Option[K, V]

WithMetricsConfig sets the metrics configuration

func WithPolicy

func WithPolicy[K comparable, V any](p policy.Policy[K, V]) Option[K, V]

WithPolicy sets the eviction policy

func WithPoolConfig

func WithPoolConfig[K comparable, V any](config PoolConfig) Option[K, V]

WithPoolConfig sets the object pool configuration

func WithRebalanceThreshold

func WithRebalanceThreshold[K comparable, V any](threshold float64) Option[K, V]

WithRebalanceThreshold sets the threshold for triggering shard rebalancing

func WithShardCount

func WithShardCount[K comparable, V any](count int) Option[K, V]

WithShardCount sets the number of shards for sharded cache

func WithStats

func WithStats[K comparable, V any](enable bool) Option[K, V]

WithStats enables statistics tracking

func WithStore

func WithStore[K comparable, V any](s store.Store[K, V]) Option[K, V]

WithStore sets the storage backend

func WithTTLConfig

func WithTTLConfig[K comparable, V any](config ttl.Config) Option[K, V]

WithTTLConfig sets the TTL configuration

type Options

type Options[K comparable, V any] struct {
	// MaxSize is the maximum number of items the cache can hold
	MaxSize int

	// TTLConfig is the configuration for TTL behavior
	TTLConfig ttl.Config

	// EnableStats enables statistics tracking
	EnableStats bool

	// Store is the storage backend to use
	Store store.Store[K, V]

	// Policy is the eviction policy to use
	Policy policy.Policy[K, V]

	// MaxMemory is the maximum memory usage in bytes (0 means unlimited)
	MaxMemory int64

	// EnableMemoryTracking enables memory usage tracking
	EnableMemoryTracking bool

	// ShardCount is the number of shards for sharded cache
	ShardCount int

	// RebalanceThreshold is the threshold for triggering shard rebalancing
	RebalanceThreshold float64

	// BatchConfig configures batch operations
	BatchConfig BatchConfig

	// CompressionConfig configures compression settings
	CompressionConfig CompressionConfig

	// PoolConfig configures object pooling
	PoolConfig PoolConfig

	// CleanupInterval is the interval for cache cleanup
	CleanupInterval time.Duration

	// MetricsConfig defines the configuration for metrics
	MetricsConfig MetricsConfig
}

Options represents cache configuration options

func DefaultOptions

func DefaultOptions[K comparable, V any]() *Options[K, V]

DefaultOptions returns the default cache options

type PoolConfig

type PoolConfig struct {
	MaxSize       int
	MinSize       int
	CleanupPeriod time.Duration
	MaxIdleTime   time.Duration
	ShrinkFactor  float64
}

PoolConfig represents configuration for the object pool

func DefaultPoolConfig

func DefaultPoolConfig() PoolConfig

DefaultPoolConfig returns the default pool configuration

type PoolStats

type PoolStats struct {
	TotalCreated   atomic.Int64
	TotalDestroyed atomic.Int64
	CurrentSize    atomic.Int64
	MaxSize        atomic.Int64
	MinSize        atomic.Int64
	LastCleanup    atomic.Value // time.Time
	LastShrink     atomic.Value // time.Time
}

PoolStats represents statistics for the object pool

type PooledCache

type PooledCache[K comparable, V any] interface {
	Cache[K, V]

	// GetPoolStats returns the current pool statistics
	GetPoolStats() *PoolStats

	// ResetPoolStats resets the pool statistics
	ResetPoolStats()

	// Cleanup performs manual cleanup of idle objects
	Cleanup()

	// OnEvent registers a callback for cache events, converting *V to V
	OnEvent(cb CacheCallback[K, V])

	// Close stops the cleanup goroutine and releases resources
	Close() error
}

PooledCache extends Cache with object pooling

func NewPooledCache

func NewPooledCache[K comparable, V any](c Cache[K, *V], config PoolConfig) PooledCache[K, V]

NewPooledCache creates a new cache with object pooling

type Stats

type Stats struct {
	Hits                  atomic.Int64
	Misses                atomic.Int64
	Sets                  atomic.Int64
	Deletes               atomic.Int64
	Clears                atomic.Int64
	Errors                atomic.Int64
	Size                  atomic.Int64
	Capacity              atomic.Int64
	Evictions             atomic.Int64
	LastOperationDuration atomic.Int64
}

Stats tracks cache statistics

func (*Stats) IncClears

func (s *Stats) IncClears()

IncClears increments the clear counter

func (*Stats) IncDeletes

func (s *Stats) IncDeletes()

IncDeletes increments the delete counter

func (*Stats) IncErrors

func (s *Stats) IncErrors()

IncErrors increments the error counter

func (*Stats) IncHits

func (s *Stats) IncHits()

IncHits increments the hit counter

func (*Stats) IncMisses

func (s *Stats) IncMisses()

IncMisses increments the miss counter

func (*Stats) IncSets

func (s *Stats) IncSets()

IncSets increments the set counter

type StatsSnapshot

type StatsSnapshot struct {
	Size                  int64
	Capacity              int64
	Hits                  int64
	Misses                int64
	Evictions             int64
	PanicCount            int64
	LastPanic             time.Time
	LastOperationDuration int64
}

StatsSnapshot is a copy of Stats without the mutex for safe return from GetStats.

Directories

Path Synopsis
Package errors provides error types and utilities for the cache package.
Package errors provides error types and utilities for the cache package.
Package internal provides internal utility functions and types used across the gencache package.
Package internal provides internal utility functions and types used across the gencache package.
Package metrics provides functionality for collecting and reporting cache performance metrics.
Package metrics provides functionality for collecting and reporting cache performance metrics.
Package policy provides different cache eviction policies like FIFO, LRU, and LFU.
Package policy provides different cache eviction policies like FIFO, LRU, and LFU.
Package store provides in-memory storage implementation for the cache.
Package store provides in-memory storage implementation for the cache.
helper
Package helper provides utility functions for store implementations
Package helper provides utility functions for store implementations
Package ttl provides functionality for managing time-to-live (TTL) values in the cache.
Package ttl provides functionality for managing time-to-live (TTL) values in the cache.

Jump to

Keyboard shortcuts

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