fix(mothership): send a late queue write to the chat a new-chat queue moved to
Merged
WA
10d ago+208+208+012345678901234567890123456789-23-23-01234567890123456789
Summary
- A busy refusal no longer vanishes into a dead new-chat key.
- The scenario: on the new-chat surface, the first message's POST is pending and a follow-up is queued, then the user presses Send-now.
- The Stop waits for the first message's admission and adopts its chat, which moves the queue to the chat's key and switches the surface.
- When the follow-up's POST was then refused as busy, the restore re-queued it under the new-chat key captured at dispatch. The message disappeared from the chat's queue, was never retried there, and could later be adopted by another new-chat surface and sent into a new chat.
- Fixed for every late write, not just this one.
migratenow records where a new-chat key moved (migratedTo), including when its queue was empty.- Every queue write that captured a key before an
awaitresolves it at write time: the dispatch's removal and restore, the direct send's re-queue after its POST, and the history check's defer and drop. Removals and defers useliveQueueKey. Inserts useliveQueuePosition, which anchors on identity: a restored message goes right after the last message still queued that was ahead of it (at dispatch, or in the chat's queue before the move), else at the head, however the queue changed meanwhile.
- Every re-queue on a chatless surface carries the surface. A Stop-failed or failed restore used to drop
heldSurface. If it landed after the surface unmounted, when nothing else marks the dead key's queue, no later mount adopted it.requeuedFieldsnow tags the surface for every reason. - Nits:
- a stale comment over
STOP_REQUEST_TIMEOUT_MSnow describes it; sendMothershipMessagenormalizes throughsendPayload().
- a stale comment over
Type of Change
- Bug fix
Testing
re-queues a Send-now refused as busy in the chat the new-chat surface moved to(DOM) reproduces the scenario. It fails on staging, where the follow-up is left under the dead key and the visible queue is empty, and passes here.send-queue-policy.test.ts: Stop-failed and failed re-queues keep their chatless surface. Fails on staging.- Store tests:
liveQueueKeyfollows a migration, including one whose queue was empty, a late insert stays behind the messages the chat's queue already held, and stays in order when messages ahead of it are removed meanwhile. - The full gate and integration tests ran on the CI runner.
Checklist
- Code follows project style guidelines
- Self-reviewed my changes
- Tests added/updated and passing
- No new warnings introduced
- I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)