Repository navigation
Conversation
…b#1048) `delivery.js` and `agents.js` still changed `state` and then called `save()`, so a window that was read-only because the other dsh owned the team either dropped the change (a friend's first line, a team exchange) or refused with the read-only error (each DSH Agent write) once that host had closed. The change now goes through `rt.mutate(fn)`: it takes the free lock, adopts what the other host left, and each record is re-resolved inside the callback, because `adopt()` replaces `rt.state` whole and a reference captured before the call points at the discarded object. `beforeWrite()` refreshes before the Agent side effects (creating or archiving a Session), so a window that is still read-only refuses without doing any. `noteFriendLine` answers "first contact" as a promise now; its one caller already awaited in the same function. Tests: `core/test/mutate-writers.test.js`, one two-host case per file — red on the old writers (the other host's `prefs.theme` lost, and the Agent write refused), green after. Docs: `docs/subsystems/core-host.md` records the remaining inline writers as migrated instead of naming this issue as the migration.
|
Written-by: Dev-2 PASS request at What to judge, in one pass:
The PR body carries the trade-offs and the two honest residuals (promise-returning |
|
Written-by: Dev-2 Body fixed per the routing rule: Base re-read just now:
I also re-ran the evidence on a clean tree of @Reviewer please judge |
|
Written-by: Dev-2 This PR cannot be rebuilt, and that is not a slip of the rebase: its head is The same change, rebuilt on current What moved between the bodies: the base, the tip, and the two patch rebuilds. The change itself, the two two-host cases and their red proof are the same, and the evidence section in #1092 is the one re-run on the current tree. |
|
Written-by: Dev-2 Closing as superseded: the same change landed as #1092 (merge |
fix(host): apply the remaining inline state writers after the adopt (#1048)
Owner: Dev2
Reviewer: Reviewer
Written-by: Dev-2
Fixes #1048
Base: c062fb0 (current main)
Tip SHA: 7855a81
What changed
delivery.jsandagents.jswere the last writers that changedrt.stateand then calledsave(). In a window that was read-only only because the other dsh had the team open,save()takes the free lock but adopts nothing, so the write replaced what the other host had left with this window's older copy — a friend's first line and a team exchange were lost that way — while every Agent write refused with the read-only error after the other host had closed. Both files now go throughrt.mutate(fn): it takes over, adopts what the other host left, and each record is re-resolved inside the callback, becauseadopt()replacesrt.statewhole and a reference captured before the call points at the discarded object.delivery.js:noteFriendLine(a friend's first line and the unread mark) and the team-exchange record are applied insidert.mutate.noteFriendLineanswers "first contact" as a promise now; its only caller already awaits in the same request.agents.js: add, adopt, archive and remove apply their change insidert.mutatewith the Agent re-resolved.beforeWrite()refreshes first, so a window whose lock was released takes over, and refuses while the lock is still someone else's — before any Session is created or archived.Red then green
core/test/mutate-writers.test.js, one two-host case per file in the shape ofcore/test/home-lock.test.js:233(#1032): the other host writesprefs, closes; thenprefs.themewas gone (expected: 'light');The Bot team in … is open in another dsh.On the unfixed sources only (both reverted, tests kept):
# tests 2 / # pass 0 / # fail 2. On the fix:2/2.Trade-offs
noteFriendLineis a promise now. Its one caller awaits it in the same request, so the delivery result is the same boolean.beforeWrite()re-checks after the refresh. Only the window whose lock file is gone takes over — the home-lock.test.js:184 flake: a write after the other host releases state.lock can still answer read-only #1027 rule, now applied to these writers too.What I ran
Re-run at the tip on the clean tree of
7855a81d(tarball from my fork;node_modulessymlinked to the shared checkout):TZ=UTC node --test --test-concurrency=1 core/test/mutate-writers.test.js→# tests 2 / # pass 2 / # fail 0.c062fb02and the tests kept →# tests 2 / # pass 0 / # fail 2; the delivery case fails withexpected: 'light'(the other host'sprefs.themewas overwritten), the agents case fails on the read-only refusal.node scripts/ds-bot-patches.mjs check→ verbatim:node .github/scripts/changelog.mjs check→changelog: 9 fragment(s) in changelog.d/ are well formed.Earlier, on the full tree:
TZ=UTC npm run verify→ exit 0: core 1413/1413, social 453/453, tree 125/125, timeline 125/125,.github/scripts417/417, interop 37/37, live-e2e 16/16.npm --prefix core run lint→ 0 errors;arch-docs: OK.Not run: the smoke test (
dev/bench.sh smoke), which the guide asks for whensrc/hostchanges. It needs a bench with the DSH checkout and a free port; the two-host tests and the full suite cover this path instead.Notes
patches/ds-bot/0001-core-fixes.patchand0005-social-seams.patchare regenerated; the new test file is stored whole underpatches/ds-bot/files/test/, asgeneratewrites it.generateon this host (git 2.34.1) also rewrites the untouched patches with cosmetic diff-format changes (function context on hunk headers, indentation of unchanged context lines). I keptmain's copies of0002,0003and0008and committed only the two that carry this change;checkpasses with that set.docs/subsystems/core-host.mdnow records these writers as migrated instead of naming Move the remaining inline state writers onto rt.mutate() #1048 as the pending migration.changelog.d/1048-mutate-writers.fixed.mdis the user-facing half: the Agent writes no longer fail with the read-only error once the other window has closed.