Expand description
§Fase 85.d — the result-memoization cache core.
This is the production-hardened runtime behind the cache primitive. The
type checker (§85.c) already proved WHAT is safe to cache (a pure tool by
construction; a widened one only with a finite TTL); this module implements
HOW, with the properties a naïve cache omits and that cause real outages:
- Content-addressed, deploy-safe, tenant-isolated keys (D85.7): the key
is a hash of
(tenant ‖ cache ‖ tool ‖ tool-declaration-fingerprint ‖ output_type ‖ selected params). A redeploy that changes a tool changes its fingerprint → a new key → no stale cross-deploy hit; the tenant is a key component → no cross-tenant leak even if a backend mis-namespaces. - Single-flight (D85.8): concurrent misses for one key compute ONCE; the rest wait for that result (no thundering herd).
- Provable-forever, never non-deterministic-forever (D85.9): enforced at compile time; the runtime simply honours the (optional) TTL.
- Production hygiene (D85.10): errors are never cached; oversized values are not cached (never truncated into a wrong value); TTL expiry is jittered (deterministically, per key) so entries don’t expire in a herd.
The CacheBackend trait lets the enterprise inject a Redis (multi-replica)
tier; with none injected, the in-process tier is fully functional
single-replica.
Structs§
- Cache
Runtime - Ties policy resolution + content-addressed key derivation + single-flight
compute-through into one call the dispatch path makes per tool. The
enterprise injects a Redis
backend+ the realtenant; the OSS default is an in-process backend under a"local"tenant. This is the whole runtime contract for §85 — a hit returns beforecomputeruns (so a budget gate placed after the lookup never sees it, D85.3). - InProcess
Cache - The OSS default single-replica tier: a bounded map with per-entry TTL (jittered), LRU eviction, a value-size bound, and single-flight miss coalescing via per-key locks.
Enums§
- Cache
Outcome - The outcome of a cache-mediated dispatch — lets the caller emit the right
cache:hit/cache:missaudit signal (D85.3) without re-deriving it.
Constants§
- DEFAULT_
CAPACITY - Default cap on the in-process tier (entries), mirroring
IdempotencyStore. - DEFAULT_
MAX_ VALUE_ BYTES - Default per-value size ceiling (bytes). An oversized result is simply not cached (D85.10) — never truncated into a wrong value.
Traits§
- Cache
Backend - A pluggable cache tier.
namespaceis the cache declaration’s name soinvalidatecan flush exactly one cache’s entries. The enterprise injects a Redis impl of this; the OSS default isInProcessCache.
Functions§
- derive_
key - Derive the content-addressed cache key.
key_argsare the selected(param_name, value)pairs (the full bound set, or thekey:subset). - parse_
duration - Parse a duration literal (
"10s","500ms","5m","2h","1d") to aDuration.Nonefor a malformed string (the lexer already guarantees the shape for attl:field, so this is defence in depth). - resolve_
tool_ cache - Resolve which
cache(if any) governs a tool’s memoization, given the whole program IR (D85.2). Precedence: an explicitcache: noneopts out; an explicitcache: <Name>selects that cache; otherwise the singledefault: truecache applies IFF the tool is eligible (provablypure, or its effects are a subset of the default’sapply_to_effects). ReturnsNonewhen nothing caches the tool. - tool_
fingerprint - The stable fingerprint of a tool’s DECLARATION — a hash of its IR spec. A redeploy that changes the tool’s provider, effects, output type, or parameters changes this, so a behaviour change can never serve a result cached under the old behaviour (D85.7).