Skip to content

feat: add opt-in replica spreading for WAL source reads - #468

Merged
beinan merged 1 commit into
mainfrom
codex/wal-source-fetch-spread-public
Oct 22, 2026
Merged

beinan merged 1 commit into
mainfrom
codex/wal-source-fetch-spread-public

Conversation

@beinan

@beinan beinan commented Oct 22, 2026 •

Copy link
Copy Markdown
Collaborator

When multiple preparers read a WAL group, every payload currently starts at the first configured voter. Add the opt-in source_read_policy: spread setting to distribute initial reads by immutable group/index while retaining every other voter as a fallback. The default remains first_voter.

This changes read placement only: exact source-pin matching, payload/schema validation, fetch concurrency, reservations and manifest authority stay in place. The selection hash touches two integers and does not hash or copy payload buffers. It applies to both buffered and streamed preparation, including remote preparers.

Validation covers real Lance recovery, exact retries and retirement, plus a network failure test that leaves only one payload endpoint reachable at a time, exercising each replica as the sole source. An independent Rust process fixture also recovered 192 MiB of acknowledged/unpublished records after all nine WAL processes were killed and reopened, followed by a preparer crash/cache loss; all 64 records and columns were read back without producer replay.

A controlled cloud comparison is queued; no throughput benefit has been established, so this option remains disabled by default. The qualified candidate includes the directory-lock fix from #465; final CI will validate the combined source after dependency promotion.

Built on merged #466 and #465. Refs #378.

Testing

  • Workspace formatting, all-target Clippy and Rust tests: 814 passed (200 optional tests ignored).
  • Service/http-client feature suite: 15 passed, 3 external-process tests ignored; separate single-reachable-replica fallback test passed.
  • Independent release-process crash/cache-loss recovery fixture passed.
  • Python: 229 passed, 2 skipped, 1 expected failure; Ruff formatting/lint and Pyright passed. Python native/server artifacts were reused after verifying unchanged source inputs and artifact hashes.

An additional 10-minute local endurance run published 9,447 MiB / 3,149 rows through two preparers. All columns and the aggregate remained correct after killing and reopening all nine WAL processes, with no producer replay or restarted publisher. Each node completed 9–10 checkpoints and collected 16–18 obsolete files. The run also had 619 producer retries and repeated leader-term changes under shared-disk pressure; it establishes recovery after this finite workload, not a throughput gain or stable capacity.

@beinan
beinan force-pushed the codex/wal-distributed-preparation-public branch from d0e8259 to 6e767f4 Compare October 22, 2026 09:47
@beinan
beinan marked this pull request as ready for review October 22, 2026 10:48
@beinan
beinan changed the base branch from codex/wal-distributed-preparation-public to main October 22, 2026 10:48
@beinan
beinan force-pushed the codex/wal-source-fetch-spread-public branch from 30e0736 to 83a158e Compare October 22, 2026 10:48
@beinan
beinan merged commit ba7549c into main Oct 22, 2026
14 checks passed
beinan added a commit that referenced this pull request Oct 22, 2026
A bounded source scan can encounter only records from other tables. The
worker previously released its claim and discarded the scan cursor, then
started from the same durable checkpoint on its next claim. A table
behind more than one scan budget of retained foreign records could
remain unpublished indefinitely.

Retain the empty-page scan hints per fixed worker assignment and move
them through claim jobs. Hints are checked against the complete table
binding, contain only quorum-observed ranges without that table's
records, and never advance durable checkpoints. Scan limits, claim
rotation and publisher fencing remain unchanged. Restart may rescan
those ranges safely.

Refs #378. Built on merged #466, #468, #469, #470 and #471.

Validation:
- Real three-replica WAL, etcd and Lance regression: a target behind 129
retained foreign records fails with the old worker and publishes its
exact payload with the fix, while another table remains unpublished.
- Materializer, worker, service and service/http-client feature Clippy
checks; ingestion and etcd-backed worker recovery suites.
- Full repository CI helper, including Rust/Python tests, formatting and
lint/type checks.

The first worker-suite run encountered an existing lease-revoke timeout
with slow local etcd synchronization. The unchanged suite passed on a
fresh run with the same storage and deadlines; the original failure was
retained. This change fixes publication progress and does not claim a
throughput improvement.
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