Repository navigation
Conversation
easyrev
marked this pull request as ready for review
September 30, 2026 03:13
easyrev
marked this pull request as draft
September 30, 2026 03:26
easyrev
force-pushed
the
feat/7895-rescannable-sources
branch
from
October 11, 2026 17:45
353501d to
2663262
Compare
This branch has not been deployed
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.
Problem
Python currently converts
LanceDatasetand Arrow dataset inputs intoRecordBatchReaders before passing them to Rust. This loses the information needed to distinguish re-scannable sources from one-shot streams.With conflict retries enabled,
merge_insertbuffers these inputs for replay, even when the original source can be scanned again. The buffer consumes additional memory and may spill to disk, regardless of whether a conflict occurs.This PR preserves source repeatability across the Python/Rust boundary, following the direction discussed in #7895 and #7368.
Implementation
Source registry
Replace the separate source classification and conversion logic with a
singledispatchregistry.Each adapter returns a
WriteSourcecontaining the schema, reader factory, and one of three modes:materialized,replayable, orstreaming.Third-party types can register their own adapters through
lance.types.coerce_source.Re-scannable provider
Add a Rust
TableProviderthat creates a fresh reader for each scan and uses the existing provider-based merge retry path.The provider invokes Python reader factories on blocking threads to avoid blocking Tokio workers. It also checks each reader's schema, including metadata.
Source eligibility
Automatically use the re-scannable path for:
Repeated scans must preserve the same schema, values, and row order. Arrow source files must remain unchanged during the operation.
Opaque Arrow scanners and sources with uncertain values or ordering retain buffered replay. This includes scanners that may consume their input only once. Callers with a stronger repeatability guarantee can provide an explicit
WriteSource.Existing materialized and one-shot input behavior remains supported. Uncommitted execution still consumes its source once without committing.
Plan analysis
Route
analyze_planthrough the same source strategy as merge execution.Also fix the shared analysis helper to propagate execution errors and use the correct output schema. Previously, a source failure could produce a misleading successful analysis result.
Validation
Correctness
Tests and checks
The full Python and Rust test suites and remote CI have not run yet.
Performance
Compared the upstream implementation and this change using matched
release-with-debugbuilds.The benchmark covers 1.125 MiB and 132 MiB inputs, three source types, and both conflict and no-conflict cases. Each configuration was measured five times, for 120 primary measurements.
Replay avoidance was verified. Eligible sources bypassed replay-buffer initialization in all measured cases. One-shot inputs and opaque scanners retained their existing behavior.
For 132 MiB inputs, replay spill decreased from approximately 132 MiB to zero.
Without a conflict, median merge latency decreased:
The performance tradeoff depends on the workload:
These measurements establish replay-buffer avoidance for the tested sources. They do not establish a general latency or memory improvement.
The results cover local warm-cache workloads. Remote storage and cold-cache performance have not been measured.
Public API
Expose
WriteSourceandcoerce_sourcethroughlance.typesas experimental APIs, without top-level re-exports.This allows third-party source adapters while leaving room to refine the reader-factory contract.
Feedback on the public API names, location, and experimental status is welcome.
Closes #7895