One inbox per document: the sign-up's deposit now lands where the owner is looking
Creating an event resolved its inbox four times at once -- from `createEvent`, from the materializer, from the watch callback and from the watch wiring -- with nothing serialising them. Three inboxes were registered for that one document inside 0.3 s, so the owner watched one while the sign-up deposited into another. That is the whole of the asymmetry: on any later connection nothing re-registers, both sides agree, and withdrawal converged immediately while a sign-up never did. Measured before: 2 of 3 fresh sign-ups NEVER converged, the deposit unfindable on every later connection. Measured after, twice: one inbox, one caller joining the in-flight resolution instead of opening a second, the deposit read back, and nothing failing to converge. The fix is two primitives rather than a lock in the middle of the data context, each unit-tested on its own: a resolve-once-per-key whose rejection is NOT memoized (unknown is not absent), and a serial task whose mid-run requests coalesce into one follow-up and which a failure cannot wedge. The single-flight wrapper is now the only caller of the underlying entry, so every call site is covered without touching any of them. Also closed on the same path: the write guard carries a monotonic cycle number, so a cycle from an earlier effect run cannot overwrite a fresher count; the field update is one statement instead of DELETE-then-INSERT, closing the window where a reader saw the field absent and read zero; and the materializer's before-value comes from a ref instead of a stale closure. What is NOT fixed, deliberately: the count still takes one connection to appear. A deposit you make into an inbox you watch produces no push, and neither does a write to your own document -- both are questions for the provider, and any app-side substitute would be the polling the doctrine forbids.
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
# Doc-debt — data-layer
|
||||
|
||||
> Presence of a block = doc to update. Processed → delete the block; no blocks left → delete this file.
|
||||
> One block = one "big change": `why` + `files` + `verify` (leaves to review).
|
||||
|
||||
## Raw markers (consolidate into blocks, then delete)
|
||||
- TOUCHED src/shared/utils/documentNuri.ts @2026-08-16 (session 0b064e8b-1717-421f-a20e-a4318ad217b1)
|
||||
- TOUCHED src/shared/utils/resolveOnce.ts @2026-08-16 (session 0b064e8b-1717-421f-a20e-a4318ad217b1)
|
||||
- TOUCHED src/shared/utils/serialTask.ts @2026-08-16 (session 0b064e8b-1717-421f-a20e-a4318ad217b1)
|
||||
- TOUCHED src/shared/utils/resolveOnce.test.ts @2026-08-16 (session 0b064e8b-1717-421f-a20e-a4318ad217b1)
|
||||
- TOUCHED src/shared/utils/serialTask.test.ts @2026-08-16 (session 0b064e8b-1717-421f-a20e-a4318ad217b1)
|
||||
- TOUCHED src/shared/utils/storeRegistry.ts @2026-08-16 (session 0b064e8b-1717-421f-a20e-a4318ad217b1)
|
||||
- TOUCHED src/shared/data/registration.ts @2026-08-16 (session 0b064e8b-1717-421f-a20e-a4318ad217b1)
|
||||
- TOUCHED src/shared/data/entityWrites.ts @2026-08-16 (session 0b064e8b-1717-421f-a20e-a4318ad217b1)
|
||||
- TOUCHED src/shared/context/FestipodDataContext.tsx @2026-08-16 (session 0b064e8b-1717-421f-a20e-a4318ad217b1)
|
||||
Reference in New Issue
Block a user