This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
This is an Echo HTTP middleware library for server-side caching of REST API responses. It's a fork of echo-http-cache that adds Redis Cluster support and two-level caching capabilities.
# Run all tests
go test -v ./...
# Run specific test
go test -v -run TestCache
# Run integration tests (requires Redis Cluster)
docker-compose up -d
go test -v -run TestCacheRedisClusterStore
docker-compose down
# Run benchmarks
go test -bench=. -benchmem
# Run two-level cache benchmarks
go test -bench=BenchmarkTwoLevel -benchmem# Build the library
go build
# Run example applications
cd example
go run redis_cluster_example.go
cd example/two_level
go run main.go# Start Redis Cluster (6 nodes: 3 masters, 3 replicas)
docker-compose up -d
# Stop Redis Cluster
docker-compose down
# Cluster ports: 17000-17005 (mapped from internal 7000-7005)The middleware intercepts GET requests and caches responses based on URL and query parameters:
-
cache.go - Core middleware implementation
CacheWithConfig()creates the Echo middleware- URL params are sorted for consistent cache keys
- Cache keys generated via FNV-64a hash of
{method}:{url} - Only successful responses (< 400 status) are cached
- Empty response bodies are not cached
-
CacheStore Interface - All store implementations follow this:
type CacheStore interface { Get(key uint64) ([]byte, bool) Set(key uint64, response []byte, expiration time.Time) Release(key uint64) }
-
memory.go - In-memory cache with eviction algorithms
- Supports LRU, LFU, MRU, MFU algorithms
- Thread-safe with sync.Mutex
- Fixed capacity with eviction on overflow
-
redis.go - Redis Standalone
- Uses
go-redis/cache/v8library - Simple key-value caching
- Uses
-
redis_cluster.go - Redis Cluster (NEW)
- True Redis Cluster support (not Ring)
- Uses
redis.ClusterClientwith 16384 hash slots Clear()method flushes all master nodes (use sparingly)
two_level_cache.go - L1 (memory) + L2 (Redis) with multiple strategies:
- WriteThrough - Writes to both L1 and L2 synchronously
- WriteBack - Writes to L1 immediately, L2 asynchronously via channel
- CacheAside - Application-managed caching
Features:
- Cache Warming - L2 hits are promoted to L1 (async by default)
- Async Operations - Buffered channel for non-blocking L2 writes
- Smart TTLs - Different expiration times for L1 (5m) and L2 (30m)
- Statistics - Tracks L1 hits, L2 hits, misses via
cache_stats.go
The async worker goroutine processes operations from asyncChan:
- Must call
Stop()on shutdown to gracefully drain the channel - Falls back to sync writes if channel is full
CacheConfig fields:
Store- Which CacheStore implementation to useExpiration- Default TTL for all pathsIncludePaths- Whitelist paths to cacheIncludePathsWithExpiration- Per-path TTLs (higher priority)ExcludePaths- Blacklist paths from caching
Path matching uses strings.Contains(), so partial matches work.
- Unit tests use
miniredisfor mocking Redis - Integration tests require actual Redis Cluster (via docker-compose)
- Tests with
_integration_test.gosuffix need Docker - Example tests in
example/example_test.goandexample/two_level/e2e_test.go
Redis Cluster has Docker networking limitations on macOS/Windows that may affect local testing. This is a Docker issue, not an implementation issue. See docs for details. Production environments are unaffected.