Repository navigation
Conversation
|
@claude review |
There was a problem hiding this comment.
Additional findings (outside the current diff — GitHub can't attach inline comments there):
-
🔴
java/lance-jni/src/optimize.rs— After this merge the Java JNI crate (lance-jni) no longer compiles, so the Java SDK cannot be built.TaskDatagained a required field,output_clustering. TheTaskData { fragments: task_data }literal at java/lance-jni/src/optimize.rs:537 was not updated. Fix: update everyTaskDataconstruction to setoutput_clustering. Ideally also carry it through the JavaTaskDataand theIntoJavaimpl at optimize.rs:363. Otherwise a plan that goes through Java loses the planner's label. [also at: rust/lance/src/dataset/optimize.rs:2379 - The Java bindings stop compiling after this merge. The JNI crate buildsTaskDatawith a struct literal at java/lance-jni/src/optimize.rs:537, and that literal lists onlyfragments.]Why this was flagged
TaskDatain rust/lance/src/dataset/optimize.rs:2369 now has a second public field,output_clustering: Option<OutputClustering>. The struct has noDefaultimpl and no..constructor. TheFromJObjectWithEnv<TaskData>impl at java/lance-jni/src/optimize.rs:532-541 still buildsTaskData { fragments: task_data }, so rustc fails with E0063 (missing fieldoutput_clustering). java/lance-jni/Cargo.toml:26 depends on the in-treerust/lanceby path, so any Java build or CI job fails on this branch; the base branch builds fine. The diff updated every other construction site (the Rust tests, index.rs, fts.rs, utils/test.rs) but not this one.IntoJava for &TaskData(optimize.rs:363-371) also drops the field. Even once the build compiles, a task exported to Java and imported back comes out withoutput_clustering: None, so a distributed Java compaction removes the label.Verification: The diff adds
pub output_clustering: Option<OutputClustering>toTaskDataat rust/lance/src/dataset/optimize.rs:2379. It has noDefaultimpl. java/lance-jni/src/optimize.rs:537-539 still buildOk(TaskData { fragments: task_data, }), so rustc rejects it with E0063. lance-jni is excluded from the top-level workspace, so a workspacecargo buildwill not catch this.
|
@claude review |
|
Triage of the
Treating it as non-reproducing here rather than root-caused; re-running the failed job for a fresh signal. Nothing in the test is being changed. One wording correction for the description (not editing it myself): "nothing is rewritten" should read "no rewritten fragment becomes visible". When the label is refused at the landing snapshot, the task's data files and the fragment id reservation have already been written; only the publishing commit is refused. |
7eb7f35 to
ff06244
Compare
134a58d to
2a444d1
Compare
|
@claude review |
…'s outputs A compaction task's outputs carried no clustering label, so compacting fragments that belong to one clustering bucket stripped the bucket. Lance cannot infer the label from the inputs, since a task may span fragments of different clusterings and an arbitrary metadata map may be object-specific. `TaskData::output_clustering` lets the planner that formed the task say what its outputs carry: the clustering id and the metadata map, stamped on every output fragment after the rewrite. Unset, outputs carry none, as before, and the commit path's existing validation refuses a label whose definition the manifest does not hold. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The Java `TaskData` has no field for an output clustering label, so exporting a labelled task would silently drop the planner's instruction and the task would rewrite unlabelled. The export now refuses such a task as unsupported and a task imported from Java is unlabelled by construction. The field doc states the worker-version precondition serde's default does not give; the no-label test compacts genuinely labelled inputs; the refusal test states what the refused publication leaves behind. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
ff06244 to
bd55af3
Compare
|
@claude review |
|
Restacked directly onto `main` at bd55af3 as a standalone change; it no longer depends on #10399. The two commits apply on main with no conflicts and the delta is unchanged: 5 files, +256/-1. Scope, for review:
Validation on this head: rustfmt clean on all five files. Compile and tests are left to CI on this head; no local gate was run. |
…ependent A compaction task's output properties were one coupled `OutputClustering` that required a clustering id to carry any metadata. They are now two independent fields on `TaskData`, typed as the `Fragment` fields they set: `output_clustering_id: Option<u32>` and `output_metadata: HashMap`. Every output fragment receives exactly these values; nothing is inferred or copied from the inputs, and the default (none, empty) is today's behaviour. Metadata alone needs no clustering definition; an explicit id is still validated against the landing manifest at commit. Serialization keeps both fields optional so tasks stay readable both ways; the Java binding, which has no fields for them, refuses a task carrying either property rather than exporting it stripped. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
@claude review |
|
c5a5ff8 replaces the coupled `OutputClustering` with two independent output properties on `TaskData`: `output_clustering_id: Option` and `output_metadata: HashMap<String, String>`, typed as the `Fragment` fields they set. Every output fragment receives exactly these values — nothing inferred or copied from inputs — and the default (none, empty) is unchanged behaviour. Metadata alone needs no clustering definition; an explicit id is still validated against the landing manifest at commit. The test covers all four combinations, serialization round-trip (fields omitted when unset), and the refused-id case, which states that a refused attempt may leave staged files and an advanced id-reservation version while publishing no replacement. The Java binding refuses a task carrying either property. Evidence: rustfmt clean locally; compile and tests are running in this PR's CI on this head. No separate build gate was run before pushing. |
Definition ids continue the manifest's maximum, so the id-only step of the output-properties test must add definition 1, not 2, to a table that has none. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
@claude review |
…iting A task whose output clustering id names no definition was refused only at commit, after every task had rewritten its data, leaving staged files behind. The planner entry point and each worker now refuse such a task before any rewrite; the commit keeps checking against the landing manifest, which is the check that counts. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
@claude review |
There was a problem hiding this comment.
Findings marked 🟡 are optional suggestions and need no follow-up push.
Still open from earlier reviews (1):
- 🔴
rust/lance/src/dataset/optimize.rs:5068—The new test compaction_outputs_carry_the_tasks_output_properties likely panics, so CI fails and the JSON round-trip an…
If you have decided not to act on one of these findings, resolve its thread (a reply alone leaves it open) and the next review stops counting it. To review this commit again now, use Re-run on its "Claude Code Review" check.
…ting The pre-rewrite check refused every id missing from the read snapshot, which also refused a definition allocated after planning that the commit would have accepted. Definition ids are never reused, so an id at or below the snapshot's `max_clustering_id` that the snapshot no longer holds can never resolve and is refused; an id above the watermark is left to the commit's check against the landing manifest. The test's serialization step builds its tasks directly instead of planning against a table that yields none, and covers both the stale and the newer id. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
@claude review |
Brings in lance-format#10440's revert of the row-order suffix relabel; the output-property changes do not touch the removed code. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
@claude review |
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
@claude review |
There was a problem hiding this comment.
The explicit output properties fit the existing contract that replacement fragments receive writer-supplied labels rather than inheriting their inputs' labels. The documented worker-version constraint remains: older workers can silently discard the requested clustering ID and metadata, so distributed callers must ensure every worker understands the new fields.
Please mark this PR with the breaking-change label.
Why
A compaction planner already chooses the final input fragments in each
TaskData. It also knows what properties the replacement fragments should carry.Previously, a task had no way to request those output properties. For example, an application compacting fragments from the same logical group could not explicitly label the replacements with that group's clustering ID and metadata.
This PR adds that output interface. It does not add grouping or decide which fragments belong together.
What the planner controls
Each task independently specifies:
Both fields apply to every output fragment of that task. ID only, metadata only, both, or neither are supported. Metadata needs no clustering definition.
For example:
Lance treats the metadata as opaque. It does not understand application buckets or enterprise clustering specs. The caller is responsible for choosing compatible inputs and meaningful output properties.
The requested values replace the output fields; they are not inferred or copied from the inputs. Defaults remain no clustering ID and empty metadata, preserving ordinary compaction behavior.
ID checks and distributed execution
A stale ID that was already allocated but is absent from the read snapshot is refused before rewriting. An ID above that snapshot's allocation watermark may have been created later, so it is left to commit-time validation.
The landing manifest must contain any requested definition when the replacement fragments commit. A commit-time refusal does not publish those replacements, although files or fragment-ID reservations may already have been staged.
Serialized tasks default missing fields to absent/empty. Workers must understand the new fields: older workers can ignore them, and this PR adds no capability negotiation. Java JNI refuses to export tasks carrying either property because its task representation cannot preserve them.
Reading order and related PR
Start with
TaskData,refuse_stale_output_clustering, the output stamping inrewrite_files, thencompaction_outputs_carry_the_tasks_output_properties.#10445 builds on this interface: it adds caller-supplied candidate groups and reuses ordinary compaction eligibility inside each group. This PR only controls the properties of already-selected tasks' outputs.