Skip to content

feat: overlay runtime cache configuration on defaults#68

Open
lan17 wants to merge 3 commits into
mainfrom
agent/runtime-config-defaults
Open

feat: overlay runtime cache configuration on defaults#68
lan17 wants to merge 3 commits into
mainfrom
agent/runtime-config-defaults

Conversation

@lan17

@lan17 lan17 commented Jul 19, 2026

Copy link
Copy Markdown
Owner

Summary

Runtime cache configuration now overlays each cached definition's optional defaultConfig field by field. This makes a provider useful as a sparse operational control instead of forcing it to repeat the complete policy on every response.

Missing policy is now an intentional disabled baseline: request-local caching defaults off, and process-local or Redis caching remains off until that layer has an effective TTL. A configured TTL with no ramp defaults to 100%.

Closes #23.

Resolution model

Runtime value Effective behavior
Provider returns null or defensive undefined Use the captured baseline unchanged
Runtime field or layer leaf is omitted/undefined Inherit the corresponding baseline leaf
requestLocal: false Explicitly disable request-local caching
ramp[layer]: 0 Explicitly disable that shared layer
No effective shared-layer TTL Disable that layer with policy_disabled
Effective TTL with no ramp Use ramp 100
Provider throws or returns a malformed config shape Fail open uncached with config_error
Runtime TTL/ramp leaf is invalid Disable only that layer with the existing bounded validation reason

The provider is still resolved once per enabled invocation, and the resulting effective configuration is used across request-local, process-local, and Redis lookup work.

Registration and mutation safety

cached() validates static defaults when the definition is registered. Static TTLs must be positive safe integers, ramps must be finite percentages from 0 through 100, layer maps must be objects, and requestLocal must be boolean when present.

Registration captures and freezes an internal snapshot, so later mutation of the caller's defaultConfig object or maps cannot change a live use case. Dynamic overlays remain intentionally fail-open because they may come from runtime configuration systems.

Public API and migration

No constructor option or policy object was added, and defaultConfig remains optional. Existing TTL/ramp map shapes are unchanged.

Observable changes:

  • Omitted DialCacheKeyConfig.requestLocal remains undefined until config resolution; its effective default is still false.
  • A non-null sparse provider result now inherits omitted baseline leaves.
  • Existing provider results that used {} or omission as a kill switch must use explicit requestLocal: false and/or per-layer ramp 0.
  • DisabledReason replaces missing_config with policy_disabled; dashboards and alerts must migrate that label value.
  • MissingKeyConfigError is removed from the public API. It was exported but never thrown, and missing policy no longer throws, so it is deleted rather than deprecated.
  • Invalid static defaults now throw during cached() registration.

There is no cache-key, Redis-key, Lua frame, serializer, adapter ownership, or client lifecycle change.

Runtime cost

The provider call count remains one per enabled invocation. The null/undefined provider path reuses the immutable registration snapshot without a merge allocation. A non-null overlay creates one small normalized config and two bounded two-layer maps.

Validation

  • 215 unit tests with 97.79% statement and 93.8% branch coverage
  • 46 Redis/Valkey integration tests
  • TypeScript typecheck
  • ESM/CJS build and declaration generation
  • Packed ESM and CommonJS runtime behavior
  • Packed consumer declaration tests, including the bounded disabled-reason union
  • Node 20 packed-package compatibility smoke
  • Two fresh independent review passes with no findings

lan17 and others added 2 commits July 19, 2026 17:52
The library has no consumers yet, and this error class was defined and
exported but never thrown anywhere. Missing policy now resolves to the
disabled baseline, so the class has no future use either. Packed
consumer tests assert the export is gone from the type declarations and
from the ESM and CommonJS runtime entries.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Combines runtime config overlays with the fallback deadline and
coalescing state work from #69. Both cached() registration validations
(defaultConfig snapshot and fallbackTimeoutMs) run before the use case
name is registered.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Overlay runtime cache configuration on documented defaults

1 participant