feat(service): a board save answers the transaction that moved its live row
Merged
CH
7d ago+190+190+012345678901234567890123456789-69-69-01234567890123456789
Service half of the board-save area of the txid rollout: saving a task's whiteboard returns the txid of the write that changed its row, and a save that changes nothing returns none. The host half (waiting on it through the board follow with confirmWrite, #4423) follows in its own PR.
Ported from the txid half of #3757 (11af552b, from that PR's earlier history; its branch luke/neon-realtime-task-record is gone). #3757 merged without it.
What changes
writeScene(packages/database/src/models/board-store.ts) returnspg_current_xact_id()::textin the upsert's ownRETURNING, as Neon's mutations guide says. It opens no extra transaction: the write already runs under the task row's lock, and that lock read now also reads where the board's live row stood before.- The save answers
txidonly where the write moved the board's live row (boardLiveStatement: a new board, a changedappliedDrawing, or a change in whether it holds an image).- This differs from the old branch. There the live row carried an
md5of the elements. Today's row is a mark without the elements, so a save that moves only elements, or changes nothing, never shows on the follow.awaitTxIdwould then sit out its whole 10 s timeout, so these saves answer no txid.
- This differs from the old branch. There the live row carried an
- Wire:
boardSaveAnswerSchema={ board, txid? }(a decimal string) is thesaveBoardoutput.HostedTaskClient.saveBoardanswers it whole. The host only adapts to the new shape here (saved.board) and doesn't wait yet.
Tests
board-store.test.ts: the first save answers a committed txid. An elements-only save and an unchanged save answer none. A save that takes the drawing and its image answers a newer committed txid.tasks-app.test.ts(web, over HTTP): the firstPUT /boardanswers a txid, and the same scene again answers none.
Checks run: typecheck for database, features, service, host and web; vitest on the files above plus compose-tasks.test.ts, board-look.test.ts and the luke-mcp app test; biome; ./scripts/oxlint.sh.
Made with Luke