KV / Once
Once
once runs a function once per key and keeps its answer: a payment
requested twice by a flaky network charges once, and the second request gets
the same receipt. With a short keep, it is a memo that many callers share:
the dashboard's panels are computed once for everyone who asks at once.
const charges = store.once<Receipt>('charges', { keep: '1d' })
const receipt = await charges.run(request.headers.get('idempotency-key')!, () =>
stripe.charge(order, { idempotencyKey: order.id }),
)charges = store.once("charges", Receipt, keep="1d")
receipt = await charges.run(request.headers["idempotency-key"], lambda: stripe.charge(order, idempotency_key=order.id))What run does
When run(key, fn) is called | It |
|---|---|
| the key has a kept answer | returns it, and runs nothing |
| the key is running elsewhere | waits for that run, in this process or another, and returns its answer |
| the key is free | runs fn, keeps its answer for keep, and returns it |
fn throws | keeps nothing: the next run runs again |
A run of the same key inside its own run is invalid, because it would wait
for itself (contract KV-11).
A memo
const panels = store.once<Panel[]>('panels', { keep: '30s' })
const data = await panels.run(`dashboard:${id}`, () => computePanels(id))panels = store.once("panels", list[Panel], keep="30s")
data = await panels.run(f"dashboard:{id}", lambda: compute_panels(id))Ten users who open the dashboard in the same second share one computation, and the next 30 seconds answer from what it kept.
What it does not promise
once runs a key at most once while its answer is kept. It cannot make an
effect happen exactly once: if the process dies after the charge and before
the answer is kept, the next run charges again. Pass the same key to the
payment provider too, so that its own deduplication covers that gap. A
declined card that must not be charged again is an answer to keep, not an
error to throw.
See also
- KV: the engine's overview.
- Requests sent twice in the Handbook, with a scene.