fed-sx-m2: Step 8c — delivery-state projection + 14 tests
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 45s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 45s
New next/kernel/delivery_state.erl folds delivery events into a
per-peer worker-shaped snapshot so the outbound queue survives
kernel restart.
Event proplist shapes:
[{type, enqueued}, {peer, _}, {activity, _}]
[{type, delivered}, {peer, _}, {cid, _}]
[{type, failed}, {peer, _}, {cid, _}, {now, _}]
[{type, dead_lettered}, {peer, _}, {cid, _}]
Projection state shape:
[{PeerId, [{peer, _}, {pending, _}, {attempts, _},
{next_retry, _}, {dead_letter, _}]}, ...]
Mirrors delivery_worker:new/1 (minus :dispatch_fn — that's the
live worker's concern) so a fresh gen_server can be hydrated
from the projection on restart.
Public API:
new/0
fold/2, fold_fn/0
peer_state/2, peers/1
pending/2, attempts/2, next_retry/2, dead_letter/2
The failed branch calls delivery_worker:backoff_for/1 directly,
so the projection and the live worker compute identical retry
slots and dead-letter thresholds. 6th failure -> dead-letter,
matching the worker.
14/14 in next/tests/delivery_state.sh covering:
- new/0 -> []
- enqueued appends to pending (FIFO)
- two peers maintain independent queues
- delivered clears matching pending entry
- failed bumps :attempts and sets :next_retry
- 6th failed -> dead-lettered (activity out of pending)
- explicit dead_lettered event moves activity to dead_letter
- peers/1 lists touched peers
- peer_state {ok, _} | not_found
- fold_fn/0 is fun/2 for projection:start_link
- unknown event type passes through
- delivered after failed clears retry state
delivery_worker.sh 17/17 unchanged, delivery_retry.sh 11/11
unchanged. Conformance preserved at 761/761.
The restart hydration helper (delivery_worker:state_from_proj/2
or similar) lands once 8b-timer can wire the live retry loop
(Blockers #3 — erlang:send_after substrate gap still open).
This commit is contained in:
@@ -566,10 +566,22 @@ a dead-letter list visible via `/admin/dead-letter`.
|
||||
self-cast or equivalent). Needs the same substrate primitive
|
||||
that `gen_server` uses for `timeout` returns. Defer behind
|
||||
substrate gap discovery for now — see Blockers.
|
||||
- [ ] **8c** — Delivery-state projection so the queue survives
|
||||
kernel restart. New `next/kernel/delivery_state.erl` fold maps
|
||||
enqueue / delivered / failed events to the worker's persistent
|
||||
shape.
|
||||
- [x] **8c** — Delivery-state projection
|
||||
(`next/kernel/delivery_state.erl`). Folds delivery events into
|
||||
per-peer worker-shaped snapshots so the outbound queue survives
|
||||
kernel restart. Event shapes:
|
||||
`[{type, enqueued|delivered|failed|dead_lettered}, {peer, _},
|
||||
{activity, _} | {cid, _}, {now, _}?]`. State shape
|
||||
`[{PeerId, WorkerProplist}, ...]` mirrors `delivery_worker:new/1`'s
|
||||
output so a fresh gen_server can be hydrated on restart. Public
|
||||
API: `new/0`, `fold/2`, `fold_fn/0`, `peer_state/2`, `peers/1`,
|
||||
per-field accessors (`pending`, `attempts`, `next_retry`,
|
||||
`dead_letter`). Uses `delivery_worker:backoff_for/1` to decide
|
||||
dead-letter promotion on the 6th failure, so the projection
|
||||
and the live worker stay in lockstep. 14/14 in
|
||||
`delivery_state.sh`. The restart-hydration helper
|
||||
(`delivery_worker:state_from_proj/2` or similar) lands when
|
||||
8b-timer wires the live retry loop.
|
||||
- [x] **8d** — `outbox:publish/2` dispatches each delivery-set
|
||||
entry to the matching worker. New `dispatch_deliveries/3` +
|
||||
`enqueue_each/2` in `outbox.erl` walk the computed
|
||||
@@ -938,6 +950,22 @@ proceed.
|
||||
|
||||
Newest first.
|
||||
|
||||
- **2026-06-07** — Step 8c: delivery-state projection. New
|
||||
`next/kernel/delivery_state.erl` folds enqueue / delivered /
|
||||
failed / dead_lettered events into a per-peer worker-shaped
|
||||
snapshot. State shape mirrors `delivery_worker:new/1`'s output
|
||||
so a fresh gen_server can be hydrated from the projection on
|
||||
kernel restart. The fail branch calls
|
||||
`delivery_worker:backoff_for/1` directly, so the projection and
|
||||
the live worker compute identical retry slots / dead-letter
|
||||
thresholds. `fold_fn/0` plugs into `projection:start_link/3`
|
||||
just like `actor_state` and `follower_graph`. 14/14 in
|
||||
`delivery_state.sh`; delivery_worker.sh 17/17 + delivery_retry.sh
|
||||
11/11 unchanged. Conformance preserved at 761/761. The
|
||||
hydration helper that loads a worker's pure state from the
|
||||
projection lands once 8b-timer can wire the live retry loop
|
||||
(Blockers #3 still open).
|
||||
|
||||
- **2026-06-07** — Step 8b-pure: retry-time bookkeeping.
|
||||
`delivery_worker` state shape gains `:next_retry` proplist
|
||||
alongside `:attempts`. `record_failure_pure/3(Cid, Now, State)`
|
||||
|
||||
Reference in New Issue
Block a user