cache

package
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Jun 8, 2026 License: MIT Imports: 14 Imported by: 0

Documentation

Overview

Package cache is part of the GoFastr framework. See https://github.com/DonaldMurillo/gofastr for documentation.

Index

Constants

View Source
const DefaultMaxCacheableBytes = 8 << 20

CacheMiddleware returns an HTTP middleware that caches GET responses using the provided Cache implementation. The X-Cache response header is set to "HIT" or "MISS" accordingly.

The middleware is conservative and refuses to cache responses that carry user-specific data or that the origin marks as uncacheable:

  • Requests other than GET are passed through untouched.
  • Requests carrying a Range header are passed through untouched and never cached: the key does not encode the Range, so a partial (206) body must not be allowed to collide with the full variant.
  • The cache key includes the request authority (Host) so distinct virtual hosts sharing one Cache do not serve each other's content.
  • Requests with Authorization or Cookie headers are not served from or written to the cache by default (RFC 9111 §3.5 / §3 default).
  • Requests with Cache-Control: no-cache or no-store bypass the stored variant and force a fresh origin fetch (no-store also skips writing the response back into the cache).
  • Responses with Set-Cookie or with Cache-Control containing private, no-store, or no-cache are never stored.
  • Responses with non-2xx/3xx status (i.e. 4xx and 5xx) are never stored. Partial-content (206) responses, or any response carrying a Content-Range header, are likewise never stored.
  • Responses carrying a Vary header are stored under a key that includes the values of every listed request header so different variants do not collide. A Vary: * response is treated as uncacheable and is never stored (RFC 9111 §4.1).

DefaultMaxCacheableBytes caps how large a response CacheMiddleware will buffer for caching (8 MiB). Larger responses stream straight to the client and are not cached, so a single huge response can't pin unbounded memory.

Variables

View Source
var ErrCacheMiss = errors.New("cache: key not found")

ErrCacheMiss is returned when a key is not found in the cache.

Functions

func CacheMiddleware

func CacheMiddleware(cache Cache, ttl time.Duration) func(http.Handler) http.Handler

func CacheMiddlewareWithLimit

func CacheMiddlewareWithLimit(cache Cache, ttl time.Duration, maxBodyBytes int) func(http.Handler) http.Handler

CacheMiddlewareWithLimit is CacheMiddleware with an explicit cap on the response size that may be buffered for caching. A response exceeding maxBodyBytes is streamed to the client and never stored. Pass 0 for unbounded buffering (the pre-cap behaviour — not recommended in production).

func GetOrSet

func GetOrSet(ctx context.Context, c Cache, key string, ttl time.Duration, dest any, loader Loader) error

GetOrSet returns the cached value for key, deserialized into dest. On a miss it invokes loader exactly once — even when many goroutines miss the same key concurrently — stores the result with the given TTL, and shares it with all waiters. A loader error is propagated and never cached.

dest must be a non-nil pointer. The loader's returned value is round-tripped through the cache (JSON) so the value written into dest is the cached form.

Types

type Cache

type Cache interface {
	// Get retrieves a value from the cache and deserializes it into dest.
	// Returns ErrCacheMiss if the key does not exist or has expired.
	Get(ctx context.Context, key string, dest any) error

	// Set stores a value in the cache with the given TTL.
	// A TTL of 0 means the entry uses the default TTL.
	Set(ctx context.Context, key string, value any, ttl time.Duration) error

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

	// Exists checks whether a key exists in the cache and has not expired.
	Exists(ctx context.Context, key string) (bool, error)

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

Cache defines the interface for cache implementations.

type Item

type Item struct {
	Key       string
	Value     any
	ExpiresAt time.Time
}

Item represents a cached entry.

type Loader

type Loader func(ctx context.Context) (any, error)

Loader produces a value to populate the cache on a miss.

type MemoryCache

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

MemoryCache is an in-memory Cache implementation backed by a map with read-write mutex for thread safety. It supports TTL-based expiration with lazy eviction on access and an optional background cleanup goroutine.

func NewMemoryCache

func NewMemoryCache(opts ...Option) *MemoryCache

NewMemoryCache creates a new in-memory cache. The background cleanup goroutine starts automatically when a cleanup interval is configured (default: 1 minute). Call Close to stop it.

func (*MemoryCache) Clear

func (mc *MemoryCache) Clear(_ context.Context) error

Clear removes all entries from the cache.

func (*MemoryCache) Close

func (mc *MemoryCache) Close()

Close stops the background cleanup goroutine.

func (*MemoryCache) Delete

func (mc *MemoryCache) Delete(_ context.Context, key string) error

Delete removes a key from the cache.

func (*MemoryCache) Exists

func (mc *MemoryCache) Exists(_ context.Context, key string) (bool, error)

Exists checks whether a key exists and has not expired.

func (*MemoryCache) Get

func (mc *MemoryCache) Get(_ context.Context, key string, dest any) error

Get retrieves a value from the cache and deserializes it into dest.

func (*MemoryCache) Len

func (mc *MemoryCache) Len() int

Len reports the number of live entries currently held. Primarily useful for tests and for observing eviction on a bounded cache.

func (*MemoryCache) Set

func (mc *MemoryCache) Set(_ context.Context, key string, value any, ttl time.Duration) error

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

type Option

type Option func(*config)

Option configures a cache instance.

func WithCleanupInterval

func WithCleanupInterval(d time.Duration) Option

WithCleanupInterval sets the interval for the background cleanup goroutine in MemoryCache. Defaults to 1 minute if not set.

func WithMaxEntries

func WithMaxEntries(n int) Option

WithMaxEntries bounds a MemoryCache to at most n live entries. Once the cap is reached, inserting a new key evicts the least-recently-used entry (LRU).

The zero-config default is UNBOUNDED (n <= 0), preserving historical behavior. Set this whenever cache keys are influenced by untrusted input to avoid unbounded memory growth (OOM/DoS). It has no effect on RedisCache, where eviction is governed by the Redis server's own maxmemory policy.

func WithPrefix

func WithPrefix(p string) Option

WithPrefix sets a key prefix for all cache operations.

func WithTTL

func WithTTL(d time.Duration) Option

WithTTL sets the default TTL for cache entries.

type RedisCache

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

RedisCache implements the Cache interface backed by a Redis store.

func NewRedisCache

func NewRedisCache(client RedisClient, opts ...Option) *RedisCache

NewRedisCache creates a new Redis-backed cache.

func (*RedisCache) Clear

func (rc *RedisCache) Clear(ctx context.Context) error

Clear removes all keys from the current Redis database.

func (*RedisCache) Delete

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

Delete removes a key from Redis.

func (*RedisCache) Exists

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

Exists checks whether a key exists in Redis.

func (*RedisCache) Get

func (rc *RedisCache) Get(ctx context.Context, key string, dest any) error

Get retrieves a value from Redis and deserializes it into dest.

func (*RedisCache) Set

func (rc *RedisCache) Set(ctx context.Context, key string, value any, ttl time.Duration) error

Set stores a value in Redis with the given TTL.

type RedisClient

type RedisClient interface {
	// Get retrieves the string value for a key. Should return a redis nil
	// error when the key does not exist.
	Get(ctx context.Context, key string) (string, error)

	// Set stores a string value with an optional expiration. A TTL of 0
	// means no expiration.
	Set(ctx context.Context, key string, value string, ttl time.Duration) error

	// Del removes one or more keys.
	Del(ctx context.Context, keys ...string) error

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

	// FlushDB removes all keys from the current database.
	FlushDB(ctx context.Context) error
}

RedisClient defines the minimal interface needed for a Redis cache backend. No specific Redis library is imported; implement this interface with your preferred Redis client (e.g. go-redis, redigo, etc.).

Jump to

Keyboard shortcuts

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