cache

package
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: Jan 24, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package cache provides response caching for MCP tools

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Cache

type Cache interface {
	// Get retrieves a cached response
	// Returns error if key not found or entry expired
	Get(ctx context.Context, key string) (*Entry, error)

	// Set stores a response in the cache
	// value MUST be JSON-serializable (json.RawMessage)
	Set(ctx context.Context, key string, value json.RawMessage, ttl time.Duration) error

	// Delete removes a cached entry
	// Returns error if key not found
	Delete(ctx context.Context, key string) error

	// Clear removes all cached entries
	Clear(ctx context.Context) error

	// Stats returns cache statistics
	Stats() CacheStats

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

Cache defines the interface for response caching All implementations must be thread-safe

func MustNew

func MustNew(config *Config) Cache

MustNew creates a cache or panics on error Useful for initialization where failure should be fatal

func New

func New(config *Config) (Cache, error)

New creates a new cache instance based on configuration Returns NoOpCache if caching is disabled

type CacheStats

type CacheStats struct {
	Hits      int64   `json:"hits"`      // Total cache hits
	Misses    int64   `json:"misses"`    // Total cache misses
	Sets      int64   `json:"sets"`      // Total set operations
	Deletes   int64   `json:"deletes"`   // Total delete operations
	Evictions int64   `json:"evictions"` // Total evictions (LRU/TTL)
	Size      int     `json:"size"`      // Current number of entries
	MaxSize   int     `json:"max_size"`  // Maximum capacity
	HitRate   float64 `json:"hit_rate"`  // Hit rate (hits / (hits + misses))
}

CacheStats holds cache statistics

type Config

type Config struct {
	// Type of cache ("short" or "long")
	Type Type `json:"type" yaml:"type"`

	// TTL is the time to live for cached entries
	// For TypeShort: seconds
	// For TypeLong: minutes
	TTL int `json:"ttl" yaml:"ttl"`

	// MaxSize is the maximum number of entries (for memory cache)
	// Ignored for file-based cache
	MaxSize int `json:"max_size" yaml:"max_size"`

	// Directory for file-based cache
	// Ignored for memory cache
	Directory string `json:"directory" yaml:"directory"`

	// Enabled enables/disables caching globally
	// Default: false (SAFE DEFAULT - must opt-in)
	// This is intentional for safety - caching is disabled by default
	Enabled bool `json:"enabled" yaml:"enabled"`

	// ToolTTL provides per-tool TTL overrides
	// Key: tool name, Value: TTL duration
	ToolTTL map[string]time.Duration `json:"tool_ttl,omitempty" yaml:"tool_ttl,omitempty"`
}

Config holds cache configuration

func DefaultConfig

func DefaultConfig() *Config

DefaultConfig returns the default cache configuration Cache is DISABLED by default for safety Tools must explicitly opt-in to caching

func (*Config) Disable

func (c *Config) Disable()

Disable disables caching

func (*Config) Enable

func (c *Config) Enable()

Enable enables caching

func (*Config) GetTTLDuration

func (c *Config) GetTTLDuration() time.Duration

GetTTLDuration returns the default TTL as a time.Duration

func (*Config) GetToolTTL

func (c *Config) GetToolTTL(toolName string) time.Duration

GetToolTTL returns TTL for a specific tool Returns default TTL if no override exists

func (*Config) IsEnabled

func (c *Config) IsEnabled() bool

IsEnabled returns whether caching is enabled

func (*Config) SetToolTTL

func (c *Config) SetToolTTL(toolName string, ttl time.Duration)

SetToolTTL sets a TTL override for a specific tool

func (*Config) Validate

func (c *Config) Validate() error

Validate validates the cache configuration If cache is disabled, no validation is performed

type Entry

type Entry struct {
	Key       string          `json:"key"`        // Cache key (SHA-256 hash)
	Value     json.RawMessage `json:"value"`      // Cached JSON response
	ExpiresAt time.Time       `json:"expires_at"` // Expiration timestamp
	CreatedAt time.Time       `json:"created_at"` // Creation timestamp
	Hits      int64           `json:"hits"`       // Number of cache hits
}

Entry represents a cached item Uses json.RawMessage to ensure JSON-safe storage

func (*Entry) Age

func (e *Entry) Age() time.Duration

Age returns how long ago the entry was created

func (*Entry) IsExpired

func (e *Entry) IsExpired() bool

IsExpired checks if the entry has expired

func (*Entry) TTL

func (e *Entry) TTL() time.Duration

TTL returns the remaining time to live Returns 0 if expired

func (*Entry) Unmarshal

func (e *Entry) Unmarshal(v interface{}) error

Unmarshal unmarshals the cached JSON value into v v must be a pointer to the target type

type KeyGenerator

type KeyGenerator struct{}

KeyGenerator generates deterministic cache keys CRITICAL: Keys must be deterministic - same logical input = same key This prevents cache misses due to Go's random map iteration order

func NewKeyGenerator

func NewKeyGenerator() *KeyGenerator

NewKeyGenerator creates a new key generator

func (*KeyGenerator) Generate

func (kg *KeyGenerator) Generate(toolName string, args map[string]interface{}) (string, error)

Generate generates a cache key from tool name and arguments Uses SHA-256 hash of canonicalized JSON

CRITICAL FIX: Arguments are normalized before hashing to ensure deterministic keys regardless of map iteration order

Example:

args1 := {"b": 2, "a": 1}  // Random order
args2 := {"a": 1, "b": 2}  // Different order
Generate("tool", args1) == Generate("tool", args2)  // ✅ Same key!

func (*KeyGenerator) GenerateSimple

func (kg *KeyGenerator) GenerateSimple(toolName string) string

GenerateSimple generates a simple cache key without arguments Useful for testing or tools with no parameters

type MemoryCache

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

MemoryCache implements an in-memory LRU cache with TTL support Thread-safe with O(1) get/set operations

Architecture:

map[string]*list.Element → O(1) lookup by key
doubly-linked list        → O(1) LRU eviction
[Front = MRU] ← → ← → [Back = LRU]

On Get: Move to front (most recently used) On Set: Add to front, evict from back if full

func NewMemoryCache

func NewMemoryCache(maxSize int, ttl time.Duration) *MemoryCache

NewMemoryCache creates a new in-memory cache

func (*MemoryCache) CleanExpired

func (c *MemoryCache) CleanExpired() int

CleanExpired removes all expired entries Returns the number of entries removed

func (*MemoryCache) Clear

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

Clear removes all entries

func (*MemoryCache) Close

func (c *MemoryCache) Close() error

Close closes the cache (clears all entries)

func (*MemoryCache) Delete

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

Delete removes an entry from the cache

func (*MemoryCache) Get

func (c *MemoryCache) Get(ctx context.Context, key string) (*Entry, error)

Get retrieves a cached entry Returns error if key not found or entry expired

func (*MemoryCache) Len

func (c *MemoryCache) Len() int

Len returns the current number of entries

func (*MemoryCache) Set

func (c *MemoryCache) Set(ctx context.Context, key string, value json.RawMessage, ttl time.Duration) error

Set stores an entry in the cache

func (*MemoryCache) Stats

func (c *MemoryCache) Stats() CacheStats

Stats returns cache statistics

type NoOpCache

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

NoOpCache is a cache implementation that does nothing Used when caching is disabled

func NewNoOpCache

func NewNoOpCache() *NoOpCache

NewNoOpCache creates a new no-op cache

func (*NoOpCache) Clear

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

Clear does nothing

func (*NoOpCache) Close

func (c *NoOpCache) Close() error

Close does nothing

func (*NoOpCache) Delete

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

Delete does nothing

func (*NoOpCache) Get

func (c *NoOpCache) Get(ctx context.Context, key string) (*Entry, error)

Get always returns cache miss

func (*NoOpCache) Set

func (c *NoOpCache) Set(ctx context.Context, key string, value json.RawMessage, ttl time.Duration) error

Set does nothing

func (*NoOpCache) Stats

func (c *NoOpCache) Stats() CacheStats

Stats returns empty stats

type Type

type Type string

Type represents the cache type

const (
	// TypeShort represents in-memory cache with TTL in seconds
	TypeShort Type = "short"

	// TypeLong represents file-based cache with TTL in minutes
	TypeLong Type = "long"
)

Jump to

Keyboard shortcuts

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