Skip to content

[SLOP(claude-opus-4-8-high)] perf(universaldb): batch leader apply and fold follower commit round-trips - #5342

Open
MasterPtato wants to merge 1 commit into
stack/slopfix-docs-self-hosting-promote-postgres-from-experimental-to-recommended-oss-multi-node-backend-zsmysqukfrom
stack/slop-claude-opus-4-8-high-perf-universaldb-batch-leader-apply-and-fold-follower-commit-round-trips-vtrtqpyp
Open

[SLOP(claude-opus-4-8-high)] perf(universaldb): batch leader apply and fold follower commit round-trips#5342
MasterPtato wants to merge 1 commit into
stack/slopfix-docs-self-hosting-promote-postgres-from-experimental-to-recommended-oss-multi-node-backend-zsmysqukfrom
stack/slop-claude-opus-4-8-high-perf-universaldb-batch-leader-apply-and-fold-follower-commit-round-trips-vtrtqpyp

Conversation

@MasterPtato

@MasterPtato MasterPtato commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

No description provided.

@MasterPtato

MasterPtato commented Jun 26, 2026

Copy link
Copy Markdown
Contributor Author

Stack for rivet-dev/rivet

Get stack: forklift get 5342
Push local edits: forklift submit
Merge when ready: forklift merge 5342

change vtrtqpyp

@claude

claude Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

PR Review: perf(universaldb): batch leader apply and fold follower commit round-trips

Re-reviewed at the current commit (a783a31, unchanged since my last pass). This PR eliminates per-row Postgres round-trips in the leader's drain loop: an in-memory Overlay folds a whole batch of winners before writing the merged write-set in O(1) statements, the lead loop splits into sibling renew_loop/drain_loop tasks so lease renewal cannot be starved by a slow drain, and the leader now encodes the commit outcome directly in the reply NOTIFY payload so followers resolve without a status SELECT. The fold_winners/Overlay logic is subtle (points-over-ranges-over-base read-through, versionstamp counters reset per winner) and apply_tests.rs covers it thoroughly against a serial oracle -- that part looks correct.

The two issues from the previous review are still present and unaddressed:

1. Rolling-update protocol break -- every commit rides the 250ms backstop during upgrade

Files: engine/packages/universaldb/src/driver/postgres/commit.rs:258 (parse_reply), engine/packages/universaldb/src/driver/postgres/resolver/mod.rs:571 (notify_after_commit)

An old-code leader sends the bare id ("123") as the NOTIFY payload. The new parse_reply only understands "id:committed:version" / "id:conflict"; splitting "123" on the colon yields no second segment, so the verb parse returns None and the reply is silently dropped as not-for-me. A new-code follower talking to an old-code leader (or vice versa, mid rolling-deploy) then falls back to the RESULT_POLL_INTERVAL (250ms) backstop for every single commit until the upgrade completes cluster-wide. Correctness is preserved (the backstop still resolves it), but this is a real latency cliff during every deploy, and there is no version negotiation guarding it. Worth either a one-line backward-compat branch in parse_reply (bare-integer payload -> treat as committed) or an explicit documented requirement to drain the commit queue before a rolling restart.

2. RUST_LOG=universaldb::driver::postgres=debug baked into the production compose template

Files: self-host/compose/template/src/docker-compose.ts:295, self-host/dev-multinode/docker-compose.yml:182,223,262

This permanently enables debug-level universaldb logging (including a log line per drain batch and per lease renewal, unbounded over process lifetime) in every deployment generated from the template, not just dev. dev-multinode is fine to have this always-on for local debugging, but the change to the shared template propagates to production-flavor configs on the next regen. Looks like a debugging aid that should either be dev-only or removed before merge.

Additional notes from this pass

  • Scope/process: the recovery_floor change in resolver/mod.rs (dropping max(durable_version, seq_high) down to durable_version alone) is a safety-critical change to the failover cold-window logic, not a mechanical perf change -- a wrong floor here means silently accepting a commit that actually conflicts with an unobserved pre-failover write, i.e. a serializability violation rather than a slow-down. The accompanying comment's proof reads correctly to me (every applied write's commit_version <= durable_version because both are set in the same apply transaction, so read_version >= durable_version implies any conflicting write is necessarily one this leader's own tracker already knows about), but this kind of consensus-safety change deserves a dedicated failover test (e.g. a leader crash mid-batch with an in-flight follower transaction whose read_version straddles the old/new floor) rather than living only as a comment inside a perf PR. None of the new tests (apply_tests.rs) exercise this path -- they are all pure in-memory fold tests.
  • Test coverage: the new bulk SQL in drain_batch (batched nextval allocation plus sort, bulk unnest-based upsert/delete, bulk status stamp via unnest) and the renew_loop/drain_loop task split (e.g. what happens when drain_loop is mid-transaction and renew_loop wins the select, hard-aborting it) have no direct test coverage against a real Postgres instance. Given this repo's stance against mocking for infra code, an integration test that drives a mixed batch (winners, conflicts, versionstamps, range clears) through the real drain_batch path would meaningfully de-risk this.
  • Commit/PR title: the commit title is "[SLOP(claude-opus-4-8-high)] perf(universaldb): ...". Per this repo's CLAUDE.md, titles must read as a pure conventional commit with no indication of agent authorship (no [SLOP(...)] prefix). Worth fixing before merge.

Minor/no-action-needed, unchanged from before: drain_loop's poll_interval is not pre-consumed before the loop (unlike renew_loop, which explicitly consumes the first tick), so the first busy-to-idle transition triggers one extra no-op drain_batch call -- harmless, just a small inconsistency in style between the two loops.

@NathanFlurry NathanFlurry changed the title [SLOP(claude-opus-4-8-high)] perf(universaldb): batch leader apply and fold follower commit round-trips perf(universaldb): batch leader apply and fold follower commit round-trips Jun 26, 2026
@MasterPtato
MasterPtato force-pushed the stack/slop-claude-opus-4-8-high-perf-universaldb-batch-leader-apply-and-fold-follower-commit-round-trips-vtrtqpyp branch from 234bfb3 to 099acee Compare June 29, 2026 23:18
@MasterPtato MasterPtato changed the title perf(universaldb): batch leader apply and fold follower commit round-trips [SLOP(claude-opus-4-8-high)] perf(universaldb): batch leader apply and fold follower commit round-trips Jun 29, 2026
@MasterPtato
MasterPtato changed the base branch from stack/slopfix-docs-self-hosting-promote-postgres-from-experimental-to-recommended-oss-multi-node-backend-zsmysquk to main August 7, 2026 00:39
@MasterPtato
MasterPtato force-pushed the stack/slop-claude-opus-4-8-high-perf-universaldb-batch-leader-apply-and-fold-follower-commit-round-trips-vtrtqpyp branch from 099acee to a783a31 Compare August 7, 2026 01:27
@MasterPtato
MasterPtato changed the base branch from main to stack/slopfix-docs-self-hosting-promote-postgres-from-experimental-to-recommended-oss-multi-node-backend-zsmysquk August 7, 2026 01:27
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