cache

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Jun 18, 2026 License: MIT Imports: 10 Imported by: 0

README

🗃️ cache — bounded in-memory caches for Starlark

Go Reference codecov binary footprint

Bounded, in-memory key-value caches with TTL expiry for Starlark scripts.

Overview

  • Independent namespaces — each new_cache() returns its own cache instance; there is no central manager or registry. Two caches never share entries.
  • Bounded — a cache never holds more than max_entries live entries; once a write would exceed the bound, the oldest-inserted entry is evicted (FIFO, not LRU).
  • Immutable snapshots — stored values round-trip through the serial codec, so a cached value is a lossless, independent copy: mutating what you put in, or what you get out, never affects the stored entry.
  • Lazy TTL — expired entries are purged on access (get / has / delete) and on the keys() / size() scans; nothing runs in the background.
  • Local capability — an in-process, in-memory store. No network, no external service, no persistence (not a wrapper over Redis/Memcached).

For the complete per-builtin reference — signatures, parameters, returns, errors, examples — and the configuration accessors, see docs/API.md.

Installation

go get github.com/starpkg/cache

Quickstart

load("cache", "new_cache")

c = new_cache(max_entries=1000, ttl=60)   # up to 1000 entries, 60s default TTL

c.set("user:42", {"name": "Ada", "tier": "pro"})
c.set("token", "abc", ttl=10)             # this entry expires in 10s

c.get("user:42")          # => {"name": "Ada", "tier": "pro"}
c.get("missing", "n/a")   # => "n/a"
c.has("token")            # => True
c.size()                  # => 2

Cached values are independent snapshots:

v = [1, 2]
c.set("nums", v)
v.append(3)               # does not affect the cached value
c.get("nums")             # => [1, 2]

Starlark API at a glance

Top-level builtin (load("cache", …)):

  • new_cache(max_entries=128, ttl=0) — create an independent cache; returns a Cache object.

Cache object methods:

  • set(key, value, ttl=None) — store a (serializable) value; ttl overrides the cache default for this entry.
  • get(key, default=None) — return a fresh copy of the value, or default if missing/expired.
  • has(key) — whether key is present and not expired.
  • delete(key) — remove key; returns whether it was present.
  • clear() — remove all entries.
  • keys() — non-expired keys, in insertion order.
  • size() — number of non-expired entries.

See docs/API.md for the full signatures, return values, errors, and examples of every builtin and method above.

Configuration

The module's options (max_entries, default_ttl) are configured via environment variables (CACHE_*) or per-option get_<key> / set_<key> accessor builtins, and seed the defaults for new_cache. A Go host can also inject a clock with cache.NewModuleWithClock for deterministic TTL testing. See the Configuration section of docs/API.md for the full option table, defaults, and accessors.

License

MIT

Documentation

Overview

Package cache provides a Starlark module offering bounded, in-memory key-value caches with TTL expiry.

Design summary (the README's "Design & semantics" section is the long form):

  • Namespacing: each new_cache() is an INDEPENDENT instance. There is no central Manager/registry — to separate namespaces, create separate caches.
  • Eviction is FIFO (oldest-inserted evicted first), NOT LRU. FIFO needs no per-access bookkeeping, so it is simple and predictable; the tradeoff is that a frequently read ("hot") key is not protected from eviction.
  • The bound is max_entries (default 128, host-configurable). Caches never hold more live entries than that.
  • Values are stored as an immutable serial snapshot (serial.dumps -> string on set, serial.loads -> fresh value on get), so a cached value is a lossless, independent copy: mutating what you put in, or what you get out, never affects the stored entry. Only serializable values can be cached; a non-serializable value makes set() return an error — there is no silent variant, and no path panics the host.
  • Concurrency: every operation is guarded by a sync.Mutex, so reads and writes are serializable and each call sees a consistent snapshot.
  • TTL expiry is lazy: an entry is purged on per-key access (get/has/delete) and on keys()/size() scans, never by a background goroutine. The clock is injectable via NewModuleWithClock for deterministic TTL testing.

Index

Constants

View Source
const ModuleName = "cache"

ModuleName is the name used in Starlark's load() for this module.

Variables

This section is empty.

Functions

This section is empty.

Types

type Module

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

Module wraps a ConfigurableModule with cache-specific functions.

func NewModule

func NewModule() *Module

NewModule creates a Module using the wall clock.

func NewModuleWithClock

func NewModuleWithClock(clock func() time.Time) *Module

NewModuleWithClock creates a Module with an injected clock (for deterministic TTL testing). clock must be non-nil.

func (*Module) LoadModule

func (m *Module) LoadModule() starlet.ModuleLoader

LoadModule returns the Starlark module loader.

Jump to

Keyboard shortcuts

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