Skip to content

feat(transaction): draft action-based transaction wire format (Transaction V2) - #7954

Draft
wjones127 wants to merge 3 commits into
mainfrom
will/oss-1530-draft-action-based-transaction
Draft

feat(transaction): draft action-based transaction wire format (Transaction V2)#7954
wjones127 wants to merge 3 commits into
mainfrom
will/oss-1530-draft-action-based-transaction

Conversation

@wjones127

@wjones127 wjones127 commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Drafts the wire format for action-based transactions (Transaction V2): a UserOperation that replaces the single legacy Operation with an ordered list of granular, composable Action deltas. This is the wire draft only — read-side fail-closed, no write path.

Layout

The V2 vocabulary lives in its own files under protos/transaction/:

  • actions.proto — the V2 vocabulary (Ref, UserOperation, UserAction, Action + the action messages), with the design rationale summarized in an in-tree file header so it stands on its own.
  • common.proto — shared building blocks (UpdateMap, KeyExistenceFilter, …) referenced by both legacy operations and V2 actions, promoted from nested Transaction messages to top-level to avoid a circular import. Wire-compatible: field numbers unchanged and none are Any-packed.
  • transaction.proto — moved into the directory; keeps the Transaction envelope, legacy operations, and the new user_operation oneof arm (field 116).

What's in the wire format

UserOperation { description, uuid, read_version, [UserAction] }
UserAction    { description, [Action] }        // human-readable step; survives squash
Action        { oneof of 19 actions }
Ref           { committed: uint64 | local: uint32 }   // one ref type for field/fragment/base ids

Design principles (fully documented in actions.proto):

  • Deltas, not post-images — actions record the change (AddDataFile, TombstoneFieldData), so compound commits and branch merge fall out uniformly.
  • Minting vs. reference-stable — minted ids (field/fragment/base) carry a Local token via a single Ref and relocate on merge/rebase; reference-stable changes key off stable coordinates and keep a post-image with a derivable delta.
  • Field-level schemaAddField / DropField / identity-preserving AlterField (per-facet, so a concurrent cast and nullability change on the same field commute). No wholesale SetSchema.
  • Index segmentsAddIndexSegment / RemoveIndexSegment / AdjustIndexCoverage (a logical index is the segments sharing a name; per-segment config duplication is a pre-existing limitation this draft doesn't fix).
  • AssertionsAssertUniqueKeys carries merge-insert's non-derivable key-existence filter as an explicit precondition.
  • Off the wire — computed conflict footprints and large derivable row-level deltas (deletion affected-rows, update matched-offsets) are recomputed at conflict time, not serialized.
  • Additive-safe — message identities and core mutation fields are pinned; discoveries land as added optional fields.

data_change markers (Delta-style, for CDC skip of compaction) and index-coverage representation carry in-tree TODOs to finalize.

Library changes (minimal, fail-closed)

Read-side rejection only:

  • One arm in TryFrom<pb::Transaction> returns Error::NotSupported for a UserOperation, with a comment forbidding lenient parsing (the try_collect contract aborts a concurrent V2 commit rather than silently skipping it).
  • Regression test test_user_operation_rejected_on_load.

No Operation enum variant, no apply / translation / conflict resolution, no write path, no Cargo feature gate, no Python/Java changes.

Verification

lance-table + lance build; new test passes; cargo fmt --all and cargo clippy -p lance-table -p lance --tests -- -D warnings clean.

🤖 Generated with Claude Code

…ction V2)

Draft the full action vocabulary for action-based transactions (Transaction
V2) directly in canonical `transaction.proto`, so it can drive the OSS-1529
squash/merge spike and the OSS-757 PMC vote.

A `UserOperation` (a new `Transaction.operation` oneof arm, field 116) is an
ordered list of `UserAction` steps, each expanding to granular `Action`
deltas. Actions record the *change* to the manifest (not a post-image), which
is what makes compound commits and branch merge fall out uniformly. Minted
identifiers (field/fragment/base ids) carry a `Local` token via a single
`Ref { committed | local }` so they relocate on merge/rebase; reference-stable
changes key off stable coordinates. Computed conflict footprints and large
derivable row-level deltas stay off the wire.

Library support is intentionally READ-side fail-closed only: a transaction
carrying a `UserOperation` is rejected on load with a clear "not supported"
error, and there is no write path, no `apply`, no translation, and no conflict
resolution yet. This keeps older writers safe (a concurrent V2 commit in the
conflict window aborts an in-flight commit rather than being silently skipped).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Ignore keyword(s) in the title.

⛔ Ignored keywords (2)
  • WIP
  • Draft

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: QUIET

Plan: Pro Plus

Run ID: d6c3e873-ac4a-40f7-89f6-e462d4db9be4

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch will/oss-1530-draft-action-based-transaction

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown
Contributor

Important

This PR touches the Lance format specification.

Substantive changes to the format specification — the .proto definitions
and the spec docs under docs/src/format/ — require a PMC vote before merge.
Minor edits such as typo fixes, wording, or formatting are excluded; use your
judgment.

If this is a meaningful format change:

  • Start a vote following the Lance community voting process.
    Format specification modifications need 3 binding +1 votes (excluding the
    proposer), held on GitHub Discussions, with a minimum voting period of 1 week.
  • Once the vote passes, link the completed vote in this PR. It should not be
    merged until the vote is linked.

@github-actions github-actions Bot added A-format On-disk format: protos and format spec docs enhancement New feature or request labels Jul 23, 2026
wjones127 and others added 2 commits July 23, 2026 14:25
…tory

Reorganize the action-based transaction (Transaction V2) wire draft into its
own files under protos/transaction/ so the design reads clearly and the shared
building blocks have a proper home:

- protos/transaction/actions.proto: the V2 vocabulary (Ref, UserOperation,
  UserAction, Action + action messages), as top-level messages. The design
  rationale is summarized in an in-tree file header (deltas vs post-images,
  minting vs reference-stable, Ref/Local resolution, field-level schema,
  index segments, what stays off the wire) so it stands on its own.
- protos/transaction/common.proto: UpdateMap/UpdateMapEntry and
  KeyExistenceFilter/ExactKeySetFilter/BloomFilter, promoted from nested
  Transaction messages to top-level so both the legacy operations and the V2
  actions can reference them without a circular import. Wire-compatible: field
  numbers unchanged and none of these types are Any-packed, so the
  fully-qualified name change is invisible on the wire.
- protos/transaction.proto moves to protos/transaction/transaction.proto and
  keeps only the Transaction envelope, legacy operations, and the
  user_operation oneof arm.

Comments use block style for IDE folding. Rust references to the promoted types
are repointed from pb::transaction::X to pb::X (mechanical, compiler-checked);
the hand-written dataset::transaction domain types are unaffected.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Refinements to the Transaction V2 wire draft (protos/transaction/actions.proto),
no behavior change:

- AddFragment / SetDeletionFile: resolve a contradiction. AddFragment's doc
  implied a freshly-minted (Local) fragment could take a deletion file via
  SetDeletionFile, but SetDeletionFile.fragment is a committed-only uint64.
  Clarify that a new fragment has no deletion vector and deletions arrive in a
  later operation once the id is committed, and document why SetDeletionFile
  takes no Ref.
- data_change: document the marker on every carrier (previously only on
  AddFragment), cross-referencing the canonical definition. Spell out its
  non-obvious meaning on AddIndexSegment / RemoveIndexSegment, where it refers
  to the indexed data rather than table rows.
- AssertUniqueKeys: note that key_fields is authoritative and the embedded
  filter.field_ids (an artifact of the shared KeyExistenceFilter type) is
  ignored.
- AdjustIndexCoverage: rename bare add / remove fields to add_fragments /
  remove_fragments for self-documentation and consistency with
  AddIndexSegment.covered_fragments.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@codecov

codecov Bot commented Jul 23, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 81.81818% with 10 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...ce/src/dataset/write/merge_insert/inserted_rows.rs 47.05% 9 Missing ⚠️
rust/lance/src/dataset/transaction.rs 97.36% 0 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-format On-disk format: protos and format spec docs enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant