feat(service): a board save answers the transaction that moved its live row

Merged
CH
7d ago
+190-69

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) returns pg_current_xact_id()::text in the upsert's own RETURNING, 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 txid only where the write moved the board's live row (boardLiveStatement: a new board, a changed appliedDrawing, or a change in whether it holds an image).
    • This differs from the old branch. There the live row carried an md5 of 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. awaitTxId would then sit out its whole 10 s timeout, so these saves answer no txid.
  • Wire: boardSaveAnswerSchema = { board, txid? } (a decimal string) is the saveBoard output. HostedTaskClient.saveBoard answers 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 first PUT /board answers 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


Devin Review