Skip to content

docs(rfc): group commit - #785

Draft
ragnorc wants to merge 4 commits into
mainfrom
rfc/group-commit
Draft

ragnorc wants to merge 4 commits into
mainfrom
rfc/group-commit

Conversation

@ragnorc

@ragnorc ragnorc commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

Draft RFC for step 3 of RFC 0067's throughput path: several writes on one branch publish in one __manifest compare-and-swap. Docs only.

Why

PR #783 measured the same-branch ceiling with concurrent-writes on the local filesystem and on RustFS at +30 ms per round trip:

What it decides

  • A batch is one graph commit. RFC 0067 sketched N commit rows per publication instead. A code survey of main plus engine: shared schema gate and the write critical section (RFC 2026-09-18) #783 found that every mapping from a commit to its __manifest version assumes one commit per version: snapshot reads, diffs, the change feed's head check and one-transaction proof, merge bases and collector roots through pinned_graph_commit, parent resolution, head rows in commit::overwrite, the lost-ack read-back, and ExactGraphHead. One commit per batch changes none of them, and needs no change to the storage format, the wire or the API.

  • Same-table inserts compose by key. Every benchmark writer inserts into one table, so batching only writes to different tables would batch nothing.

    • The benchmark's insert into the @key type Chunk is staged as an upsert. So composition covers strict inserts and upserts whose staged transaction only appends, meaning no key matched.
    • It uses Lance's documented distributed-write shape: the raw, unassigned fragments are committed in one transaction, and Lance assigns fragment ids, row ids and version metadata at commit.
  • Detached commits happen after admission and are stamped with the batch's head. RFC 0067's sketch had writers commit before submitting. The collector's staging rule would then sweep an admitted entry whose captured head had fallen behind. Committing after admission leaves that rule unchanged.

  • Admission. An entry is admitted when:

    • every commit since its capture is one this publisher made, within a bounded horizon;
    • no writer since then has touched its footprint.

    The footprint is its written tables, every table its execution opened (including a predicate scan that matched nothing), and the tables its validation read. For append-only entries the rule is relaxed to disjoint inserted ids. The batch is conflict-serializable in admission order.

  • Scope.

    • A batch holds the writes of one actor, and a write with an expected head publishes alone.
    • Merge, schema apply, index builds and Optimize are unchanged.

Review

An independent Codex review of the first draft found two ways the admission rule was unsound, plus five further gaps. All were verified against the code and fixed in 970f3f68:

  • write skew through zero-match scans;
  • edge non-key @unique;
  • the materialized versus effective head;
  • the rollback, which is now a cap of one plus a horizon of zero;
  • the retry contract;
  • keyed inserts staged as upserts;
  • inserted ids that aren't carried on the staged write.

The RFC's decision log lists each one.

Checks

check-docs.py, typos and check-agents-md.sh pass. The RFC 0067 edit adds a pointer in its Unresolved questions, away from the lines #783 changes.

Several writes on one branch publish in one __manifest compare-and-swap as
one graph commit. A per-branch publisher admits queued entries by footprint,
composes same-table strict inserts by key into one detached commit, and
publishes through the unchanged single-commit publisher. Motivated by the
same-branch ceiling measured for the shared schema gate (#783) and by #784.
Footprints include execution reads (write skew through zero-match scans);
edge non-key @unique is exclusive; the materialized and effective heads are
distinct; the rollback is cap one plus horizon zero; the retry contract is
stated as it is; the append-only class covers insertion-only upserts, which
is how the benchmark's keyed inserts are staged; carrying exact ids is a
prerequisite.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant