Repository navigation
feat(ingest): add opt-in streamed file preparation - #464
Merged
Merged
Conversation
This was referenced Oct 22, 2026
beinan
force-pushed
the
codex/wal-materializer-phase-metrics
branch
from
October 22, 2026 07:42
2832599 to
3373e0c
Compare
beinan
changed the base branch from
codex/wal-materializer-phase-metrics
to
main
October 22, 2026 08:36
beinan
force-pushed
the
codex/wal-streamed-preparation-public
branch
from
October 22, 2026 08:36
befea08 to
a28e13e
Compare
beinan
added a commit
that referenced
this pull request
Oct 22, 2026
## Summary A single managed table currently prepares all of its files inside one publishing worker, so adding workers does not parallelize that table's data preparation. Add an opt-in Rust `preparer` role that divides one immutable, pinned publication plan across bounded remote services. Each service reads its assigned records directly from WAL and passes Arrow handles into the existing Lance writers. The publisher exchanges only plan references and fragment metadata, joins every partition and records the complete aggregate through the existing durable Prepare and fenced publication protocol. The services resolve the deployment-authorized table registry, verify the exact plan and source pins through quorum reads, and use authenticated bounded requests, job slots, memory reservations and a volatile result cache. Admitted jobs survive disconnected observers. A missing or failed partition cannot publish a partial result; after durable Prepare, recovery needs no preparer cache. Losing a cache earlier may redo unpublished immutable files under the existing orphan-cleanup contract. The option is disabled when `preparation` is absent. This changes no WAL wire format or Lance OSS code. It does not provide orphan deletion, a hard bound on Lance encoder RSS, or a demonstrated throughput improvement. ## Testing - Integration coverage uses two authenticated HTTP services over real TLS WAL and Lance files: missing-service failure, healthy-partition cache reuse, disjoint source reads, complete aggregate recovery after both caches disappear, and full payload verification. - Independent release-process qualification passed: two producers acknowledge 192 MiB before publication, all nine WAL processes are killed and reopened, one preparer is missing, and its completed sibling is killed to lose its cache. Restarting both preparers publishes all 64 original records exactly once with complete payload, aggregate-count, read-only and negative-verifier checks and no producer replay. All source reads, decodes and file writes occur in preparers; publisher counters remain zero. This is local process recovery, not Kubernetes volume-loss qualification. - Materializer-only and service/http-client all-target Clippy passed. Feature tests: 11 passed, 3 external-process fixtures ignored by the ordinary run. Workspace formatting, all-target Clippy and Rust tests passed, as did Python pytest (229 passed, 2 skipped, 1 xfailed), Ruff and Pyright. Unchanged native/server artifacts were reused after verifying source inputs and hashes. Final-head CI and prerequisite merges are still required. - Kubernetes 1/2/4-preparer scaling is queued behind the current qualified-control experiment. No distributed throughput result or sustained-capacity claim yet. Refs #378. Built on merged #464 and #465. The distributed preparation implementation matches the independently qualified release; the base additionally contains the engine directory-lock fix #465 and prerequisite test-helper feature gate. Final-head CI validates that combined source. Feature-only validation also covers the test fixtures with `worker` and `service` enabled independently, including the actual preparer recovery test.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Materializers currently fetch and decode an entire pinned publication before starting Lance file writers. Add an experimental, default-off
worker.publication.pipeline_preparationoption that feeds bounded Arrow streams into Lance 13 writers as records become available, without payload reserialization.Both paths preserve the same immutable plan, whole-record partitioning and complete descriptor aggregation. Writers share fetch/decode permits; blocking decode retains its permit and source reservation through cancellation, and all admitted writers finish before a failure is returned. No partial descriptor set can be prepared or published.
This distributes preparation within one worker only. Lance encoder workspace remains outside the source reservation, streamed
blob_writetiming includes source waiting, and no throughput improvement or end-to-end zero-copy is claimed. A matched short cloud comparison completed full payload and aggregate checks before and after restart in both modes. In the common 60–150 second window, buffered publication was 60.17–60.63 MiB/s and streamed publication 57.23–57.87 MiB/s. Including drain, the respective rates were 52.62–54.15 and 57.33–59.05 MiB/s. These are one-run sampling/clock bounds, not statistical confidence or sustained capacity; initial leaders differed and the streamed run experienced term changes. The results do not establish a steady-window throughput improvement or support enabling the option by default.Testing
Refs #378. Built on merged #463 and #465. The streamed materializer implementation matches the qualified candidate; the base additionally contains the engine directory-lock fix #465. A test helper is additionally gated to the features that use it; materializer-only and service/http-client all-target Clippy pass with that correction.
Validation follow-up: the HTTP test publisher helper is compiled only with
http-client, matching its callers. Local all-target Clippy passes withworker,materializer, andhttp-client,materializerseparately; production code is unchanged by this test fix. Final-head CI must pass before merge.