Repository navigation
build(storage): upgrade lance to 13.0.0 - #1072
Conversation
Lance 13 (lance#8944) lists `data/` through `max(retained-manifest floor,
now - 7 days)` and deletes every listed file no attached manifest references.
It still never reads a `d{n}.manifest`, so on a graph table, whose one
attached version is its `v1` create, a stock `cleanup_old_versions` run of
any policy keeps every detached manifest and deletes every detached commit's
data file older than a week; the pins that name those versions then open and
fail to read. Lance 11 listed `data/` only below the retained floor, which
left every detached file alone, so the never-call-stock-cleanup fence is now
load-bearing rather than hygiene.
- `lance_surface_guards.rs::stock_cleanup_sweeps_a_week_old_detached_data_file_lance_13`
pins both halves on a chain of two detached commits: the fresh file
survives on the seven-day floor alone, the aged one is swept, both
manifests stay, and both detached versions open but cannot scan.
- `docs/dev/lance.md` Cleanup row states the Lance 13 rule and names the
guard and the `forbidden_apis.rs` deny-list entry as owners; the testing
map lists the guard.
- The maintenance guide tells operators that `omnigraph cleanup` is the only
cleanup to run against a graph root and what a stock Lance cleanup does.
- The upgrade guide gains the v0.14 Lance 13 statement (format 16 and V2_2
unchanged, no `omnigraph upgrade`, full-text indexes stay searchable, the
fleet and backup-rollback rules unchanged) within the page's line budget.
- The release note carries the cleanup warning.
|
Alignment note from #1016 (branch create at a commit), for this bump's API audit. #1016 adds two dependencies on Lance behavior:
|
|
Recommendation: merge. I found no blocking defect at This pull request moves the Lance family from 11.0.0 to 13.0.0. Graph storage format stays 16. Data files stay V2_2. The full-text analyzer generation stays What changes for OmniGraphLance 13 changes three behaviors that this engine relies on. Stock Flat nearest search no longer forces one scan partition. Lance 13 keeps the KNN sort through V2 payload hydration. Merge-insert now fails on duplicate source keys ( Contracts that still holdI checked these in the Lance 13.0.0 tag A catalog overwrite with Compaction of a graph table still commits Spilled row lineage is opt-in (
Session cache defaults stay 6 GiB for indexes and 1 GiB for metadata. Issue #702 stays open. DataFusion stays 54.0.0. Arrow stays 58.3.0. The toolchain stays 1.97.1. Lance 13 requires Rust 1.91. Two Local manifest discovery still returns an unquoted inode-mtime-size tag. object_store 0.14 quotes the same token. The adapter quotes only a bare three-part hex tag on a direct local path. A quoted tag is left unchanged. A mismatch is a cache miss.
Scalar index delta segments can still return a stale value for an updated row. The guard that expects that bug passed. A whole-index rebuild stays required. Production vector builds stay LiabilityThe clone adapter no longer repairs inherited index bases and no longer rejects a malformed external fragment-reuse index before publication. Production branch creation clones the The new operator hazard is external cleanup. The code path is unchanged. The Lance rule is new, and the docs and the guard carry it. The DST golden changes 17 FindingsBlocking: none. Optional: the upgrade guide says a graph the new fleet has written is not qualified for the old reader. See the inline note. Keep the mixed-fleet ban. Issues this does not close#970, #971, #895, #702, #925, #841, #958, and #1094 stay open. #1094 is the order of OmniGraph's own cleanup. It is separate from the Lance stock-cleanup rule above. ValidationGitHub checks on I ran these locally on that commit. All passed.
I did not re-run the full GQT corpus, the DST suite, or the S3 and Azure jobs. Those checks are green on this commit. The rollback binary in CI is the PR base Inline comment on |
What & why
Upgrade the complete Lance family from 11.0.0 to 13.0.0, preserving graph format 16, explicit V2_2 files, and the existing full-text analyzer generation. Format-16 graphs need no storage conversion. Genuine predecessor/candidate tests cover reads, writes, search, Blob contents, history, maintenance, rollback, and whole-root backup restoration.
The adapters preserve pagination faults/accounting, opaque object-store context, strict manifest-cache identity, and typed completion evidence. Retire three obsolete compatibility paths:
SourceDedupeBehavior::Fail; typed source uniqueness checks remain. The indexed-update regression keeps the same BTREE UUID/coverage while the rewritten row moves to an uncovered fragment, then updates it again. Lance'sprocessed_row_idsstill exists; the upstream fix is the index-coverage prefilter correction in lance#6965.__manifest, which has no fragment-reuse index. Keep exact source-version refusal, scoped main-source manifest-location reuse, local ETag normalization, and configured commit-handler/session/failure semantics. A native nested-clone guard requires a cold indexed query. Remove the now-unused coreprostand devlance-linalgdependency edges; package versions and transitive feature selections remain unchanged.The cleanup guard now puts the attached manifest's embedded timestamp at −10 days and a detached-only data file at −8 days, on opposite sides of Lance 11's retained floor and Lance 13's seven-day listing cutoff. It preserves the inline transaction when changing the fixture timestamp. Cleanup documentation distinguishes file age from snapshot age: an old detached-only file can make a recent descendant or the current graph unreadable; files shared with retained attached versions remain protected.
Consolidate two remaining adapters: use Lance's native
ChainedWrappingObjectStorein place ofStackedWrapper, preserving memo-outside-probe order and pagination refusal; remove the test-only genericstage_merge_insertadapter, trait forwarding and duplicate key validator. The four staged behavior owners now exercise productionstage_keyed_writeusing keyed fixtures, with update-only rebase semantics and all substantive assertions retained. Refresh the affected comments, source-guard delimiter and vocabulary inventory. These APIs predate Lance 13; this follow-up removes duplication without changing the storage contract (282 fewer lines).Backing issue / RFC
Checklist
Validation
Adapter consolidation (
91ecceef)0a36f664: 1,693 unclassified and 529 stale occurrences. CI explicitly disables that audit. Exact baseline-source and final-source scans prove this follow-up introduces no mismatches and removes two existing unclassified occurrences; the obsolete helper's inventory entries are removed.Retirement follow-up (
0a36f664)(old_versions, data_files_removed)is(0, 0)on 11 versus(0, 1)on 13. The equally old attached file remains readable on 13; the fresh descendant of the swept detached file does not. The temporary predecessor test edit was restored.RUSTFLAGS=-C code-model=large,RUST_MIN_STACK=16777216); the linker emitted the previously observed large unwind-table warning, without build or runtime failures.0a36f664, including CI Gate and GQ Logic Tests. Workspace: 4,717 passed, 39 intentionally skipped, plus two doctests. Storage compatibility: 147 passed (8 cross-version, 100 engine, 4 Lance-column and 35 protocol guards). The full configured GQT corpus passes all 399 cases; DST passes 108 tests with 31 intentionally ignored, including its storage-cost golden. RustFS passes 121 default and 3 failpoint tests; Azure passes all 15 required tests and the shared-container inventory check.Prior upgrade qualification
0881e10b: 4,734 passed, zero failed, 39 intentionally ignored.0881e10bbuilt with the archive workflow flags. The genuine Lance 11 ↔ 13 journey passed against the release CLI; three existing process journeys passed against the release CLI/server (query and mutation, branch merge, full cluster lifecycle). Version/commit/channel and all three binary startup checks passed. The release CLI also passed real init/load/read journeys against both isolated S3 and Azure emulators, with no skips. The macOS linker reported its large unwind-table warning; builds and runtime checks succeeded.4faecee9: 4,720 workspace tests plus 2 doctests; all 399 GQT corpus cases and the served/DST-backed groups; all 16 S3 and 15 Azure required cells; 108 DST tests and shipped-engine Clippy. All three corrected overlay tests explicitly pass in debug. Storage compatibility ran 8 storage-upgrade cases (including 6 genuine predecessor journeys), 100 engine upgrade/recovery tests, 4 Lance-column tests and 35 protocol guards without failures or runtime skips.4faecee9keeps all debug positives and asserts typed release refusal, real cleanup with zero deletions and intact original/overlay inventories, plus continued modern/legacy planning. All 577 corrected engine unit tests pass in release, as do core/catalog units; the other optimized targets are unchanged by this test-only correction. Formatting, docs, 35 source guards and the environment-access guard also pass. Other-platform archive packaging remains release-workflow-owned.Compatibility boundaries
lance11.0.0-frostem1.20260821.3-v1; package pins and the unchanged analyzer dependency graph are separately audited.0a62bb7b2aa5b99b012f413807c216277f7f9596.Audited DST cost-baseline changes
The genuine Lance 11 source at
0a62bb7b2aa5b99b012f413807c216277f7f9596passes the existing golden. The Lance 13 candidate reproduces the same 17 read-count changes seen in CI. Temporary object-store tracing independently accounts for every successful physicalget_optscall in both deterministic replays (26 ledgers total); its totals exactly equal everyl.getrow. All other golden counters, including writes, deletes, lists and adapter calls, are unchanged. Failed-read counts are unchanged. Tracing has been restored before final qualification.The reductions come from Lance 13 batching adjacent page/column requests in the catalog's
__manifest/.../data/*.lancefiles. This includes page-initialization metadata inside data files, not fewer native_versions/*.manifestreads. Lance 13'sRequestBatchgathers ranges before the I/O scheduler coalesces them, and primitive-page initialization combines cache-miss ranges. The same data-file inventory is accessed for every changed label. For example, one merge reads three catalog data files in 9+14+9 requests under 11 and 4+8+4 under 13. A diff reads the same file in 16 requests under 11 and 8 under 13; distinct 4-byte headers at0..4and768..772become one0..772request, and the nearby column payloads become a shared range. Request sizes/offsets are diagnostic evidence, not new byte-count goldens.Two labels also expose a separate native index-metadata cost: scalar-index opening under existing v0 fragment reuse now first loads the raw index listing to choose the remapping generation, then the legacy v0 opener looks up that listing again. Where that lookup is not cached, it costs a native table-manifest HEAD plus payload GET.
AddFriendhas two additional pairs and_audithas three additional pairs in aggregate. These are included below, rather than attributed to batching or hidden by a broader budget.l.get11 → 13No unexplained counter movement remains. The small/large history pairs remain equal. This approves deliberate regeneration of the exact deterministic memory-store golden; it is not a wall-clock or cloud-performance claim.
Exact upstream mechanisms
SchedulerContextat lines 3089–3109.find_frag_reuse_index_meta, which loads the listing again. Lance 11 called the legacy opener directly.