cache

package
v1.0.2 Latest Latest
Warning

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

Go to latest
Published: Dec 30, 2025 License: MIT Imports: 10 Imported by: 0

README

Cache Package

A flexible, provider-based caching library for Go that supports multiple backend storage systems including in-memory, Redis, and Memcache.

Features

  • Multiple Providers: Support for in-memory, Redis, and Memcache backends
  • Pluggable Architecture: Easy to add custom cache providers
  • Type-Safe API: Automatic JSON serialization/deserialization
  • TTL Support: Configurable time-to-live for cache entries
  • Context-Aware: All operations support Go contexts
  • Statistics: Built-in cache statistics and monitoring
  • Pattern Deletion: Delete keys by pattern (Redis)
  • Lazy Loading: GetOrSet pattern for easy cache-aside implementation

Installation

go get github.com/bitechdev/ResolveSpec/pkg/cache

For Redis support:

go get github.com/redis/go-redis/v9

For Memcache support:

go get github.com/bradfitz/gomemcache/memcache

Quick Start

In-Memory Cache
package main

import (
    "context"
    "time"
    "github.com/bitechdev/ResolveSpec/pkg/cache"
)

func main() {
    // Initialize with in-memory provider
    cache.UseMemory(&cache.Options{
        DefaultTTL: 5 * time.Minute,
        MaxSize:    10000,
    })
    defer cache.Close()

    ctx := context.Background()
    c := cache.GetDefaultCache()

    // Store a value
    type User struct {
        ID   int
        Name string
    }
    user := User{ID: 1, Name: "John"}
    c.Set(ctx, "user:1", user, 10*time.Minute)

    // Retrieve a value
    var retrieved User
    c.Get(ctx, "user:1", &retrieved)
}
Redis Cache
cache.UseRedis(&cache.RedisConfig{
    Host:     "localhost",
    Port:     6379,
    Password: "",
    DB:       0,
    Options: &cache.Options{
        DefaultTTL: 5 * time.Minute,
    },
})
defer cache.Close()
Memcache
cache.UseMemcache(&cache.MemcacheConfig{
    Servers: []string{"localhost:11211"},
    Options: &cache.Options{
        DefaultTTL: 5 * time.Minute,
    },
})
defer cache.Close()

API Reference

Core Methods
Set
Set(ctx context.Context, key string, value interface{}, ttl time.Duration) error

Stores a value in the cache with automatic JSON serialization.

Get
Get(ctx context.Context, key string, dest interface{}) error

Retrieves and deserializes a value from the cache.

SetBytes / GetBytes
SetBytes(ctx context.Context, key string, value []byte, ttl time.Duration) error
GetBytes(ctx context.Context, key string) ([]byte, error)

Store and retrieve raw bytes without serialization.

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

Removes a key from the cache.

DeleteByPattern
DeleteByPattern(ctx context.Context, pattern string) error

Removes all keys matching a pattern (Redis only).

Clear
Clear(ctx context.Context) error

Removes all items from the cache.

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

Checks if a key exists in the cache.

GetOrSet
GetOrSet(ctx context.Context, key string, dest interface{}, ttl time.Duration,
         loader func() (interface{}, error)) error

Retrieves a value from cache, or loads and caches it if not found (lazy loading).

Stats
Stats(ctx context.Context) (*CacheStats, error)

Returns cache statistics including hits, misses, and key counts.

Provider Configuration

In-Memory Options
&cache.Options{
    DefaultTTL:     5 * time.Minute,  // Default expiration time
    MaxSize:        10000,             // Maximum number of items
    EvictionPolicy: "LRU",             // Eviction strategy (future)
}
Redis Configuration
&cache.RedisConfig{
    Host:     "localhost",
    Port:     6379,
    Password: "",         // Optional authentication
    DB:       0,          // Database number
    PoolSize: 10,         // Connection pool size
    Options:  &cache.Options{
        DefaultTTL: 5 * time.Minute,
    },
}
Memcache Configuration
&cache.MemcacheConfig{
    Servers:      []string{"localhost:11211"},
    MaxIdleConns: 2,
    Timeout:      1 * time.Second,
    Options: &cache.Options{
        DefaultTTL: 5 * time.Minute,
    },
}

Advanced Usage

Custom Provider
// Create a custom provider instance
memProvider := cache.NewMemoryProvider(&cache.Options{
    DefaultTTL: 10 * time.Minute,
    MaxSize:    500,
})

// Initialize with custom provider
cache.Initialize(memProvider)
Lazy Loading Pattern
var data ExpensiveData
err := c.GetOrSet(ctx, "expensive:key", &data, 10*time.Minute, func() (interface{}, error) {
    // This expensive operation only runs if key is not in cache
    return computeExpensiveData(), nil
})
Query API Cache

The package includes specialized functions for caching query results:

// Cache a query result
api := "GetUsers"
query := "SELECT * FROM users WHERE active = true"
tablenames := "users"
total := int64(150)

cache.PutQueryAPICache(ctx, api, query, tablenames, total)

// Retrieve cached query
hash := cache.HashQueryAPICache(api, query)
cachedQuery, err := cache.FetchQueryAPICache(ctx, hash)

Provider Comparison

Feature In-Memory Redis Memcache
Persistence No Yes No
Distributed No Yes Yes
Pattern Delete No Yes No
Statistics Full Full Limited
Atomic Operations Yes Yes Yes
Max Item Size Memory 512MB 1MB

Best Practices

  1. Use contexts: Always pass context for cancellation and timeout control
  2. Set appropriate TTLs: Balance between freshness and performance
  3. Handle errors: Cache misses and errors should be handled gracefully
  4. Monitor statistics: Use Stats() to monitor cache performance
  5. Clean up: Always call Close() when shutting down
  6. Pattern consistency: Use consistent key naming patterns (e.g., "user🆔field")

Example: Complete Application

package main

import (
    "context"
    "log"
    "time"
    "github.com/bitechdev/ResolveSpec/pkg/cache"
)

type UserService struct {
    cache *cache.Cache
}

func NewUserService() *UserService {
    // Initialize with Redis in production, memory for testing
    cache.UseRedis(&cache.RedisConfig{
        Host: "localhost",
        Port: 6379,
        Options: &cache.Options{
            DefaultTTL: 10 * time.Minute,
        },
    })

    return &UserService{
        cache: cache.GetDefaultCache(),
    }
}

func (s *UserService) GetUser(ctx context.Context, userID int) (*User, error) {
    var user User
    cacheKey := fmt.Sprintf("user:%d", userID)

    // Try to get from cache first
    err := s.cache.GetOrSet(ctx, cacheKey, &user, 15*time.Minute, func() (interface{}, error) {
        // Load from database if not in cache
        return s.loadUserFromDB(userID)
    })

    if err != nil {
        return nil, err
    }

    return &user, nil
}

func (s *UserService) InvalidateUser(ctx context.Context, userID int) error {
    cacheKey := fmt.Sprintf("user:%d", userID)
    return s.cache.Delete(ctx, cacheKey)
}

func main() {
    service := NewUserService()
    defer cache.Close()

    ctx := context.Background()
    user, err := service.GetUser(ctx, 123)
    if err != nil {
        log.Fatal(err)
    }

    log.Printf("User: %+v", user)
}

Performance Considerations

  • In-Memory: Fastest but limited by RAM and not distributed
  • Redis: Great for distributed systems, persistent, but network overhead
  • Memcache: Good for distributed caching, simpler than Redis but less features

Choose based on your needs:

  • Single instance? Use in-memory
  • Need persistence or advanced features? Use Redis
  • Simple distributed cache? Use Memcache

License

See repository license.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Close

func Close() error

Close closes the cache and releases resources.

func ExampleCustomProvider

func ExampleCustomProvider()

ExampleCustomProvider demonstrates using a custom provider.

func ExampleDeleteByPattern

func ExampleDeleteByPattern()

ExampleDeleteByPattern demonstrates pattern-based deletion (Redis only).

func ExampleGetOrSet

func ExampleGetOrSet()

ExampleGetOrSet demonstrates the GetOrSet pattern for lazy loading.

func ExampleInMemoryCache

func ExampleInMemoryCache()

ExampleInMemoryCache demonstrates using the in-memory cache provider.

func ExampleMemcacheCache

func ExampleMemcacheCache()

ExampleMemcacheCache demonstrates using the Memcache cache provider.

func ExampleRedisCache

func ExampleRedisCache()

ExampleRedisCache demonstrates using the Redis cache provider.

func Initialize

func Initialize(provider Provider)

Initialize initializes the cache with a provider. If not called, the package will use an in-memory provider by default.

func SetDefaultCache

func SetDefaultCache(cache *Cache)

SetDefaultCache sets a custom cache instance as the default cache. This is useful for testing or when you want to use a pre-configured cache instance.

func UseMemcache

func UseMemcache(config *MemcacheConfig) error

UseMemcache configures the cache to use Memcache storage.

func UseMemory

func UseMemory(opts *Options) error

UseMemory configures the cache to use in-memory storage.

func UseRedis

func UseRedis(config *RedisConfig) error

UseRedis configures the cache to use Redis storage.

Types

type Cache

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

Cache is the main cache manager that wraps a Provider.

func GetDefaultCache

func GetDefaultCache() *Cache

GetDefaultCache returns the default cache instance. Initializes with in-memory provider if not already initialized.

func NewCache

func NewCache(provider Provider) *Cache

NewCache creates a new cache manager with the specified provider.

func (*Cache) Clear

func (c *Cache) Clear(ctx context.Context) error

Clear removes all items from the cache.

func (*Cache) Close

func (c *Cache) Close() error

Close closes the cache and releases any resources.

func (*Cache) Delete

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

Delete removes a key from the cache.

func (*Cache) DeleteByPattern

func (c *Cache) DeleteByPattern(ctx context.Context, pattern string) error

DeleteByPattern removes all keys matching the pattern.

func (*Cache) DeleteByTag added in v0.0.119

func (c *Cache) DeleteByTag(ctx context.Context, tag string) error

DeleteByTag removes all keys associated with the given tag.

func (*Cache) Exists

func (c *Cache) Exists(ctx context.Context, key string) bool

Exists checks if a key exists in the cache.

func (*Cache) Get

func (c *Cache) Get(ctx context.Context, key string, dest interface{}) error

Get retrieves and deserializes a value from the cache.

func (*Cache) GetBytes

func (c *Cache) GetBytes(ctx context.Context, key string) ([]byte, error)

GetBytes retrieves raw bytes from the cache.

func (*Cache) GetOrSet

func (c *Cache) GetOrSet(ctx context.Context, key string, dest interface{}, ttl time.Duration, loader func() (interface{}, error)) error

GetOrSet retrieves a value from cache, or sets it if it doesn't exist. The loader function is called only if the key is not found in cache.

func (*Cache) Remember

func (c *Cache) Remember(ctx context.Context, key string, ttl time.Duration, loader func() (interface{}, error)) (interface{}, error)

Remember is a convenience function that caches the result of a function call. It's similar to GetOrSet but returns the value directly.

func (*Cache) Set

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

Set serializes and stores a value in the cache with the specified TTL.

func (*Cache) SetBytes

func (c *Cache) SetBytes(ctx context.Context, key string, value []byte, ttl time.Duration) error

SetBytes stores raw bytes in the cache with the specified TTL.

func (*Cache) SetBytesWithTags added in v0.0.119

func (c *Cache) SetBytesWithTags(ctx context.Context, key string, value []byte, ttl time.Duration, tags []string) error

SetBytesWithTags stores raw bytes in the cache with the specified TTL and tags.

func (*Cache) SetWithTags added in v0.0.119

func (c *Cache) SetWithTags(ctx context.Context, key string, value interface{}, ttl time.Duration, tags []string) error

SetWithTags serializes and stores a value in the cache with the specified TTL and tags.

func (*Cache) Stats

func (c *Cache) Stats(ctx context.Context) (*CacheStats, error)

Stats returns statistics about the cache.

type CacheStats

type CacheStats struct {
	Hits          int64          `json:"hits"`
	Misses        int64          `json:"misses"`
	Keys          int64          `json:"keys"`
	ProviderType  string         `json:"provider_type"`
	ProviderStats map[string]any `json:"provider_stats,omitempty"`
}

CacheStats contains cache statistics.

func GetStats

func GetStats(ctx context.Context) (*CacheStats, error)

GetStats returns cache statistics.

type MemcacheConfig

type MemcacheConfig struct {
	// Servers is a list of memcache server addresses (e.g., "localhost:11211")
	Servers []string

	// MaxIdleConns is the maximum number of idle connections (default: 2)
	MaxIdleConns int

	// Timeout for connection operations (default: 1 second)
	Timeout time.Duration

	// Options contains general cache options
	Options *Options
}

MemcacheConfig contains Memcache-specific configuration.

type MemcacheProvider

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

MemcacheProvider is a Memcache implementation of the Provider interface.

func NewMemcacheProvider

func NewMemcacheProvider(config *MemcacheConfig) (*MemcacheProvider, error)

NewMemcacheProvider creates a new Memcache cache provider.

func (*MemcacheProvider) Clear

func (m *MemcacheProvider) Clear(ctx context.Context) error

Clear removes all items from the cache.

func (*MemcacheProvider) Close

func (m *MemcacheProvider) Close() error

Close closes the provider and releases any resources.

func (*MemcacheProvider) Delete

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

Delete removes a key from the cache.

func (*MemcacheProvider) DeleteByPattern

func (m *MemcacheProvider) DeleteByPattern(ctx context.Context, pattern string) error

DeleteByPattern removes all keys matching the pattern. Note: Memcache does not support pattern-based deletion natively. This is a no-op for memcache and returns an error.

func (*MemcacheProvider) DeleteByTag added in v0.0.119

func (m *MemcacheProvider) DeleteByTag(ctx context.Context, tag string) error

DeleteByTag removes all keys associated with the given tag.

func (*MemcacheProvider) Exists

func (m *MemcacheProvider) Exists(ctx context.Context, key string) bool

Exists checks if a key exists in the cache.

func (*MemcacheProvider) Get

func (m *MemcacheProvider) Get(ctx context.Context, key string) ([]byte, bool)

Get retrieves a value from the cache by key.

func (*MemcacheProvider) Set

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

Set stores a value in the cache with the specified TTL.

func (*MemcacheProvider) SetWithTags added in v0.0.119

func (m *MemcacheProvider) SetWithTags(ctx context.Context, key string, value []byte, ttl time.Duration, tags []string) error

SetWithTags stores a value in the cache with the specified TTL and tags. Note: Tag support in Memcache is limited and less efficient than Redis.

func (*MemcacheProvider) Stats

func (m *MemcacheProvider) Stats(ctx context.Context) (*CacheStats, error)

Stats returns statistics about the cache provider. Note: Memcache provider returns limited statistics.

type MemoryProvider

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

MemoryProvider is an in-memory implementation of the Provider interface.

func NewMemoryProvider

func NewMemoryProvider(opts *Options) *MemoryProvider

NewMemoryProvider creates a new in-memory cache provider.

func (*MemoryProvider) CleanExpired

func (m *MemoryProvider) CleanExpired(ctx context.Context) int

CleanExpired removes all expired items from the cache.

func (*MemoryProvider) Clear

func (m *MemoryProvider) Clear(ctx context.Context) error

Clear removes all items from the cache.

func (*MemoryProvider) Close

func (m *MemoryProvider) Close() error

Close closes the provider and releases any resources.

func (*MemoryProvider) Delete

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

Delete removes a key from the cache.

func (*MemoryProvider) DeleteByPattern

func (m *MemoryProvider) DeleteByPattern(ctx context.Context, pattern string) error

DeleteByPattern removes all keys matching the pattern.

func (*MemoryProvider) DeleteByTag added in v0.0.119

func (m *MemoryProvider) DeleteByTag(ctx context.Context, tag string) error

DeleteByTag removes all keys associated with the given tag.

func (*MemoryProvider) Exists

func (m *MemoryProvider) Exists(ctx context.Context, key string) bool

Exists checks if a key exists in the cache.

func (*MemoryProvider) Get

func (m *MemoryProvider) Get(ctx context.Context, key string) ([]byte, bool)

Get retrieves a value from the cache by key.

func (*MemoryProvider) Set

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

Set stores a value in the cache with the specified TTL.

func (*MemoryProvider) SetWithTags added in v0.0.119

func (m *MemoryProvider) SetWithTags(ctx context.Context, key string, value []byte, ttl time.Duration, tags []string) error

SetWithTags stores a value in the cache with the specified TTL and tags.

func (*MemoryProvider) Stats

func (m *MemoryProvider) Stats(ctx context.Context) (*CacheStats, error)

Stats returns statistics about the cache provider.

type Options

type Options struct {
	// DefaultTTL is the default time-to-live for cache items.
	DefaultTTL time.Duration

	// MaxSize is the maximum number of items (for in-memory provider).
	MaxSize int

	// EvictionPolicy determines how items are evicted (LRU, LFU, etc).
	EvictionPolicy string
}

Options contains configuration options for cache providers.

type Provider

type Provider interface {
	// Get retrieves a value from the cache by key.
	// Returns nil, false if key doesn't exist or is expired.
	Get(ctx context.Context, key string) ([]byte, bool)

	// Set stores a value in the cache with the specified TTL.
	// If ttl is 0, the item never expires.
	Set(ctx context.Context, key string, value []byte, ttl time.Duration) error

	// SetWithTags stores a value in the cache with the specified TTL and tags.
	// Tags can be used to invalidate groups of related keys.
	// If ttl is 0, the item never expires.
	SetWithTags(ctx context.Context, key string, value []byte, ttl time.Duration, tags []string) error

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

	// DeleteByTag removes all keys associated with the given tag.
	DeleteByTag(ctx context.Context, tag string) error

	// DeleteByPattern removes all keys matching the pattern.
	// Pattern syntax depends on the provider implementation.
	DeleteByPattern(ctx context.Context, pattern string) error

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

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

	// Close closes the provider and releases any resources.
	Close() error

	// Stats returns statistics about the cache provider.
	Stats(ctx context.Context) (*CacheStats, error)
}

Provider defines the interface that all cache providers must implement.

type RedisConfig

type RedisConfig struct {
	// Host is the Redis server host (default: localhost)
	Host string

	// Port is the Redis server port (default: 6379)
	Port int

	// Password for Redis authentication (optional)
	Password string

	// DB is the Redis database number (default: 0)
	DB int

	// PoolSize is the maximum number of connections (default: 10)
	PoolSize int

	// Options contains general cache options
	Options *Options
}

RedisConfig contains Redis-specific configuration.

type RedisProvider

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

RedisProvider is a Redis implementation of the Provider interface.

func NewRedisProvider

func NewRedisProvider(config *RedisConfig) (*RedisProvider, error)

NewRedisProvider creates a new Redis cache provider.

func (*RedisProvider) Clear

func (r *RedisProvider) Clear(ctx context.Context) error

Clear removes all items from the cache.

func (*RedisProvider) Close

func (r *RedisProvider) Close() error

Close closes the provider and releases any resources.

func (*RedisProvider) Delete

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

Delete removes a key from the cache.

func (*RedisProvider) DeleteByPattern

func (r *RedisProvider) DeleteByPattern(ctx context.Context, pattern string) error

DeleteByPattern removes all keys matching the pattern.

func (*RedisProvider) DeleteByTag added in v0.0.119

func (r *RedisProvider) DeleteByTag(ctx context.Context, tag string) error

DeleteByTag removes all keys associated with the given tag.

func (*RedisProvider) Exists

func (r *RedisProvider) Exists(ctx context.Context, key string) bool

Exists checks if a key exists in the cache.

func (*RedisProvider) Get

func (r *RedisProvider) Get(ctx context.Context, key string) ([]byte, bool)

Get retrieves a value from the cache by key.

func (*RedisProvider) Set

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

Set stores a value in the cache with the specified TTL.

func (*RedisProvider) SetWithTags added in v0.0.119

func (r *RedisProvider) SetWithTags(ctx context.Context, key string, value []byte, ttl time.Duration, tags []string) error

SetWithTags stores a value in the cache with the specified TTL and tags.

func (*RedisProvider) Stats

func (r *RedisProvider) Stats(ctx context.Context) (*CacheStats, error)

Stats returns statistics about the cache provider.

Jump to

Keyboard shortcuts

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