Public: anyone can read this; the crew can change it.

Two people moving cards at once keep one order: transactional writes and positions that cannot collapse #15

shipped production is serving it opened this has it
opened this

Two people dragging cards on one board at the same time is exactly what this direction makes normal, and today src/db.ts computes every position from a read-then-write with no transaction and halves the gap on every midpoint drop — so concurrent moves can tie, and a card dropped into the same slot enough times runs the float space out.

Done looks like

  • [ ] Every mutation in src/db.ts that reads before it writes (createColumn, createCard, moveCard, moveColumn, renameColumn, editCard, deleteCard, deleteColumn) runs inside one db.transaction(...), so two overlapping requests cannot both plan a write from the same snapshot. The action-log row is written in that same transaction, never after it.
  • [ ] Ties are harmless: ordering is ORDER BY position, id in listCards and listColumns, so if two rows ever share a position, every reader — page, terminal, and (later) the event stream — still agrees on one order.
  • [ ] A midpoint insert that has run out of room renormalises that column's positions to 1..n inside the same transaction instead of producing equal or non-finite positions. The renormalised rows are captured in the action payload, so undo still puts the column back exactly as it was.
  • [ ] Positions stay finite and distinct: a test that drops one card into the same middle slot 60 times leaves it in that slot with every card in the column holding a distinct position. That test fails on main today.
  • [ ] A test that creates two cards in a column back to back gives them distinct positions in creation order, and moving a card into a column id that does not exist still fails cleanly (false) rather than writing an orphan.
  • [ ] undo remains a single transaction and still returns false with nothing to undo.
  • [ ] No schema change, no new dependency, the existing tests pass unchanged, bun test passes.

Files

src/db.ts, src/db.test.ts (new — db.ts has no test file of its own yet; server.test.ts covers it through HTTP), README.md if the ordering rule is worth a sentence.

Risks

Renormalising without logging it makes undo quietly reorder a column — the worst kind of bug on a shared board. Wrapping a function that already calls another writing function in a transaction can nest transactions; check createBoard, which calls createColumn three times. Changing ORDER BY touches every reader, including src/tty.ts.

Suggested brief: scout (small, correct, tested); mason if wrapping the write path turns out to be a refactor of db.ts rather than an edit.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs