DB Docs
Getting Started
AI/LLM: This documentation page is available in plain markdown format at/db/latest/docs/contributing/oracle-reviews/2026-10-08-partial-update-aborted-batch.md
Content temporarily unavailable
Partial-update history after an aborted source batch#
Reviewed revision: the commit that adds this record on fix-partial-update-retention, based on main f6aba314e.
Finding#
The partial-update campaign of packages/db/tests/collection-state-retention-oracle.property.test.ts (collection-state.optimistic-history-partial) failed on main for the random seed -526998278. It failed the same way on fe284ccbd. Shrunk history:
- The source row is { id: 1, a: 0, b: 0, c: 0 }.
- An open sync batch deletes row 1, and then aborts before acceptance.
- A partial sync update writes row 1 with c: -1. The partial lane omits c.
The Collection published c: -1. The model allowed only c: 0.
Which account failed#
The driver failed. Production and the model were correct.
- The law: in the default partial row update mode, an update that omits a field merges into the source row, so the held value of that field remains. The authority is the oracle's opening prose and the Collection's rowUpdateMode: 'partial' contract.
- The driver records the source's own rows (sourceRows) so that it can write a partial update with c omitted. On an aborted open batch, it restored sourceKeys but not sourceRows. Row 1 was therefore missing from sourceRows, and the driver wrote the next update as a whole row with c: -1.
- Production merged the whole row that it received. That is correct for the write the driver sent. The model predicted the write that the history described. The mismatch was in the driver's translation of the history.
Repair#
- An open batch keeps rowsBefore with keysBefore, and an abort restores both.
- The driver throws Partial update of unknown source row if a partial update finds no held source row. A future drift between sourceKeys and sourceRows then fails as a driver error, not as a product mismatch.
- A pinned case, merges a partial update after an aborted source delete, replays the shrunk history. It asserts that the open batch aborted and that the partial update was a distinguishing one.
Evidence#
| Check | Original driver | Fixed driver |
|---|---|---|
| Pinned case | Fails: c: -1 published, c: 0 allowed | Passes |
| Seed -526998278 replay | Fails | Passes |
| Fixed and random partial campaigns | Pass (the fixed seed never reached this history) | Pass |
A mutant that keeps rowsBefore but does not restore it fails the pinned case and one of the two partial campaigns with the new driver error.
No production code changed, so this change has no changeset.
ORC outcomes#
| Requirement | Outcome |
|---|---|
| ORC-001 | Applicable. The law and its authority are above. |
| ORC-002 | Applicable. The model is unchanged and does not read production. |
| ORC-003 | Applicable. The pinned case has a comment that states the law and the history. |
| ORC-004 | Applicable. The open/abort and partial dimensions already existed. The fixed seed did not combine an aborted delete with a later partial update, so the pinned case supplies that history. |
| ORC-005 | Applicable. The driver now sends the write that the history describes. The new invariant rejects an inconsistent driver state. |
| ORC-006 | Applicable. The original driver and the no-restore mutant both fail at the intended checkpoint. |
| ORC-007 | Applicable. The fixed and random campaigns are unchanged. The direct replay of the reported seed and path passes. |
| ORC-008 | Applicable. The driver's source state now has one consistent restore point for keys and rows. |
| ORC-009 | Not applicable. No model term changed. |
| ORC-010 | Not applicable. No cleanup or shrinking change. |
| ORC-011 | Not applicable. No shared-fault hypothesis. |
| ORC-012 | Applicable. This record. |
| ORC-013 | Not applicable. No threshold law. |
| ORC-014 | Not applicable. No controlled provider. |