s3-orchestrator

cache

import "github.com/afreidah/s3-orchestrator/internal/cache"

Package cache provides an object data cache layer that sits between the orchestrator and storage backends, reducing API calls and egress by serving repeated reads from local storage.

Index

type Entry

Entry holds a cached object’s data and metadata.

type Entry struct {
    Data        []byte
    ContentType string
    ETag        string
    Metadata    map[string]string
}

func (*Entry) Size

func (e *Entry) Size() int64

Size returns the approximate memory footprint of this entry in bytes.

type EntryMeta

EntryMeta holds the metadata to store alongside cached object data.

type EntryMeta struct {
    ContentType string
    ETag        string
    Metadata    map[string]string
}

type MemoryCache

MemoryCache is a size-aware LRU cache backed by an in-memory map and doubly-linked list. Evicts least-recently-used entries when the total size exceeds MaxSize. Entries expire after TTL.

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

func NewMemoryCache

func NewMemoryCache(cfg MemoryConfig) (*MemoryCache, error)

NewMemoryCache creates a new in-memory LRU cache with the given configuration.

func (*MemoryCache) Admit

func (c *MemoryCache) Admit(size int64) bool

Admit reports whether an entry whose data is approximately size bytes would be accepted by the cache. Compares against max_object_size only; total-cache capacity is handled by LRU eviction at PutBytes time. The “approximately” caveat exists because an Entry’s stored size also includes ContentType + ETag + Metadata key/value bytes, which the caller does not know until PutBytes runs - in practice these are tens of bytes versus the body size and never matter for admission.

func (*MemoryCache) Clear

func (c *MemoryCache) Clear() int

Clear removes every entry and zeroes the LRU. Updates gauges so the cache_size_bytes / cache_entries dashboards reflect the flush immediately, without waiting for the next Get/Put.

func (*MemoryCache) Get

func (c *MemoryCache) Get(key string) (*Entry, bool)

Get returns the cached entry if present and not expired. On hit, the entry is promoted to the front of the LRU list.

func (*MemoryCache) Invalidate

func (c *MemoryCache) Invalidate(key string)

Invalidate removes a single key from the cache.

func (*MemoryCache) InvalidatePrefix

func (c *MemoryCache) InvalidatePrefix(prefix string) int

InvalidatePrefix removes every entry whose key starts with prefix and returns the number of entries dropped. Walks the items map (O(n)) so callers should expect cost proportional to cache size, not match count. Holds c.mu for the duration to keep map iteration safe.

func (*MemoryCache) PutBytes

func (c *MemoryCache) PutBytes(key string, data []byte, meta EntryMeta)

PutBytes stores pre-buffered data in the cache. Callers must have called Admit first to confirm the size fits the per-entry limit; this method does not re-check that condition on the body bytes. Falls back to a silent no-op if even after evicting every existing entry the new entry cannot fit (e.g. metadata pushed it over MaxSize).

func (*MemoryCache) Stats

func (c *MemoryCache) Stats() Stats

Stats returns current cache utilization.

type MemoryConfig

MemoryConfig holds tuning parameters for the in-memory cache.

type MemoryConfig struct {
    MaxSize       int64         // maximum total cache size in bytes
    MaxObjectSize int64         // maximum size of a single cached object in bytes
    TTL           time.Duration // time before an entry expires
}

type ObjectCache

ObjectCache caches object data to avoid repeated backend fetches. Implementations must be safe for concurrent use by multiple goroutines.

The interface separates admission decision from buffering so callers can refuse to read oversized payloads into memory in the first place: check Admit(size), and only buffer + PutBytes when admitted.

type ObjectCache interface {
    // Get returns the cached entry for the given key, or false if not cached.
    Get(key string) (*Entry, bool)

    // Admit reports whether an entry of the given size would be accepted by
    // the cache (i.e., size <= max_object_size). O(1). Callers consult this
    // before buffering data; oversized streams stay unread on the wire.
    Admit(size int64) bool

    // PutBytes stores pre-buffered data for key. Callers must have called
    // Admit first to confirm size fits. Implementations may evict LRU
    // entries to make room. Best-effort: if the cache cannot store the
    // entry (e.g. capacity exhausted by larger entries), the call is a
    // silent no-op.
    PutBytes(key string, data []byte, meta EntryMeta)

    // Invalidate removes a single key from the cache.
    Invalidate(key string)

    // InvalidatePrefix removes every entry whose key starts with the given
    // prefix and returns the count of entries that were dropped. Empty
    // prefix matches every entry (equivalent to Clear) - callers that
    // want a clean flush should use Clear directly so the metric counter
    // reflects the operator's intent.
    InvalidatePrefix(prefix string) int

    // Clear removes every entry. Returns the number of entries that were
    // dropped. Used by the admin cache-flush endpoint to support cache-cold
    // performance characterisation.
    Clear() int

    // Stats returns current cache utilization statistics.
    Stats() Stats
}

type Stats

Stats reports current cache utilization.

type Stats struct {
    Entries   int
    SizeBytes int64
    MaxBytes  int64
}

Generated by gomarkdoc