Atomically insert an entry only if no entry exists for scopedKey.
Used as a claim step by the middleware to close the concurrent-miss
race (two parallel requests with the same fresh key both seeing
miss and both executing side effects). Returns true if the
caller "won" the claim and should proceed to run the handler;
false if another request claimed first (the caller should treat
the result as a replay or conflict on re-check).
Store an entry, overwriting any existing entry with the same
scopedKey. Used by the middleware to replace the in-flight
placeholder (written via putIfAbsent at claim time) with the final
response after the handler completes.
Delete an entry. Used by the middleware to release the claim when the handler fails — errors MUST NOT be cached, so the placeholder is rolled back on error so a retry can re-execute.
OptionalprobeOptional startup probe. Implementations that wrap an external store
(e.g., pgBackend) should implement this to eagerly validate the
connection before the server starts accepting traffic. Called by
probeIdempotencyStore() and by serve() when readinessCheck is
wired. Throws a descriptive error when the backend is unreachable or
the required schema is missing.
OptionalcloseOptional hook for implementations that need to release resources
(close pools, clear timers). Called by store.close().
OptionalclearOptional test-harness hook that drops every cached entry without
releasing backend resources. Used by AdcpServer.compliance.reset()
between storyboards so idempotency cache hits from one storyboard
don't replay into the next (shared brand domain, same key prefix).
Production backends that can't cheaply flush everything (e.g., a
shared Postgres cluster) should leave this undefined — the reset
hook refuses to run when this method is missing unless the caller
explicitly opts in with { force: true }.
Storage backend interface. Swap implementations for memory, Postgres, Redis, etc.
Keys are already composed as
{principal}\u001f{key}(or with extra scope segments for per-session tools) before reaching the backend — backends don't need to know about scoping. The separator is U+001F (unit separator) rather than NUL because Postgres TEXT columns reject NUL bytes; either way the middleware's key-pattern validation (^[A-Za-z0-9_.:-]{16,255}$) guarantees the separator cannot appear in a legitimate key.Object-identity contract. Implementations MUST NOT return the same object reference on subsequent
getcalls — the middleware injects envelope fields (replayed: true, echo-backcontext) onto the returned value, and a shared reference would leak those mutations across requests. Implementations that store values by reference (e.g.,memoryBackend) MUST deep-clone on read; implementations that serialize (e.g.,pgBackendvia JSON) get this for free.