Skip to content

feat(batch): typed backward-references deletes; rename flag to propagate_backward_references_when_unsure - #950

Open
QuantumExplorer wants to merge 5 commits into
developfrom
claude/grovedb-propagate-backward-refs-f5d2e0
Open

feat(batch): typed backward-references deletes; rename flag to propagate_backward_references_when_unsure#950
QuantumExplorer wants to merge 5 commits into
developfrom
claude/grovedb-propagate-backward-refs-f5d2e0

Conversation

@QuantumExplorer

@QuantumExplorer QuantumExplorer commented Sep 9, 2026

Copy link
Copy Markdown
Member

What

Rename (breaking for 6.0.0 crate consumers). propagate_backward_references on InsertOptions, DeleteOptions and BatchApplyOptions is now propagate_backward_references_when_unsure. Semantics are unchanged. The name says what the flag buys: when the caller does not know whether the element it displaces carries backward references, GroveDB reads it and finds out, then propagates or cascades accordingly.

Two typed batch deletes that pin that decision per op, whatever the batch flag says:

  • GroveOp::DeleteWithCascade (sort tag 21): always reads the element and runs exactly the flagged delete's bookkeeping. Every referrer chain cascades, each affected reference must allow cascade_on_update, and a deleted BidirectionalReference is de-registered from its target.
  • GroveOp::DeleteWithNoBackwardsReferenceCheck (sort tag 22): never reads the element. Registered references are left dangling, exactly as an unflagged live delete leaves them.

Plain Delete keeps following the batch flag. Constructors: delete_with_cascade_op, delete_with_no_backwards_reference_check_op, plus _estimated_op twins.

How

  • expand_backward_references_ops gains flag_on. An unflagged batch carrying a cascade op runs the pass in per-op mode: only the cascade ops are read and planned; other ops are not read (no extra cost) and only their certain effects are staged into the overlay, so the cascade resolves against the batch's outcome. The M4 conflict rules apply unchanged. The fresh-subtree pre-scan runs only under the flag, since it reads every tree-writing op.
  • A no-check delete in a flagged batch is not read either: its position is staged as gone. A test pins that it costs byte-identically to a plain delete in an unflagged batch.
  • Average/worst-case estimators charge the displaced-state fan-out and the delete probe per op, not per flag.
  • Gating: GROVE_V4 full batches only. Pre-V4 versions, partial batches, and partial-batch add-on ops refuse both ops with NotSupported rather than silently degrading to a plain delete. apply_operations_without_batching gets the same gate.

Design notes for reviewers

  • The described behavior is SQL-style CASCADE, not SET NULL. A nullify variant would need a new on-disk representation for a nullified reference and its own consent semantics, and is deliberately not part of this change.
  • GROVE_V4 is unreleased, so changing what the flag governs on plain Delete is free of replay concerns. The rename itself is a source-level break for consumers of the 6.0.0 crates.

Testing

  • 10 new tests in batch_backward_references_tests.rs: live-vs-batch root equality for both ops, de-registration when deleting a reference, consent, mixed unflagged batches (cascade op cascades while a plain delete dangles), conflict fail-closed, the without-batching path, pre-V4 and partial-batch refusals, sort-tag pins.
  • 2 new tests in batch_backward_references_cost_tests.rs: worst-case estimate covers an actual unflagged cascade; fan-out follows the op, not the flag, and is byte-stable pre-V4.
  • Full grovedb suite green with full,estimated_costs (3453 + integration + doctests); cargo clippy --all-targets -D warnings clean on grovedb and grovedb-version.

Docs: CHANGELOG (Added + BREAKING Changed), adr/bidirectional_references.md, docs/book/src/batch-operations.md, docs/crates/grovedb.md.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added per-operation delete modes for cascading backward-reference cleanup or skipping backward-reference checks.
    • Added estimated variants with matching cost behavior.
    • Available in Grove V4+ batches, but not partial batches or older versions.
  • Breaking Changes

    • Renamed the backward-reference option to propagate_backward_references_when_unsure; behavior remains unchanged for existing operations.
  • Documentation

    • Documented typed delete behavior, version restrictions, reference handling, and cost-estimation rules.

…ate_backward_references_when_unsure

Rename the `propagate_backward_references` field of `InsertOptions`,
`DeleteOptions` and `BatchApplyOptions` to
`propagate_backward_references_when_unsure` (semantics unchanged). The name
says what the flag buys: when the caller does not know whether the element
it displaces carries backward references, GroveDB reads it and finds out.

Callers that do know can now say so per batch op:

- `GroveOp::DeleteWithCascade` (sort tag 21) always reads the deleted
  element and runs the flagged delete's bookkeeping: every referrer chain
  cascades (consent via `cascade_on_update` required) and a deleted
  `BidirectionalReference` is de-registered from its target.
- `GroveOp::DeleteWithNoBackwardsReferenceCheck` (sort tag 22) never reads
  it; registered references are left dangling, exactly as an unflagged
  live delete leaves them.

Plain `Delete` keeps following the batch flag. The backward-references
preprocessor gains a `flag_on` parameter: an unflagged batch carrying a
cascade op runs in per-op mode, where only the cascade ops are read and
planned, the other ops pay nothing extra, and only their certain effects
are staged so the cascade resolves against the batch's outcome. The M4
conflict rules apply unchanged. Estimators charge the fan-out per op rather
than per flag.

Both ops require GROVE_V4 full batches: pre-V4 versions, partial batches
and partial-batch add-on ops refuse them with `NotSupported` instead of
silently degrading to a plain delete; `apply_operations_without_batching`
gets the same gate.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 25595014-9160-4d43-b8fb-b511fa9f46e2

📥 Commits

Reviewing files that changed from the base of the PR and between 5ee44c4 and 6681236.

📒 Files selected for processing (3)
  • grovedb/src/batch/backward_references.rs
  • grovedb/src/tests/batch_backward_references_cost_tests.rs
  • grovedb/src/tests/batch_backward_references_tests.rs

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

The batch API adds typed deletes that either cascade backward-reference cleanup or skip backward-reference checks. It adds per-operation expansion and cost handling, rejects typed deletes in unsupported contexts, and renames the propagation option across code, tests, and documentation.

Changes

Backward-reference delete behavior

Layer / File(s) Summary
Typed delete contract and execution
grovedb/src/batch/mod.rs, grovedb/src/batch/options.rs, grovedb/src/operations/delete/...
Adds DeleteWithCascade and DeleteWithNoBackwardsReferenceCheck, constructors, ordering tags, validation, execution paths, and GROVE_V4/full-batch restrictions.
Per-operation expansion and cost estimation
grovedb/src/batch/backward_references.rs, grovedb/src/batch/estimated_costs/*
Adds per-operation backward-reference processing and separate average- and worst-case cost models for typed deletes.
Propagation option rename and routing
grovedb/src/operations/{insert,delete}/..., grovedb/src/batch/options.rs, grovedb-version/src/version/*
Renames the propagation option to propagate_backward_references_when_unsure and updates routing and forwarding while preserving its default behavior.
Documentation and behavioral validation
CHANGELOG.md, adr/*, docs/*, grovedb/src/tests/*
Documents typed delete semantics and validates cleanup, cost parity, restrictions, sort tags, and updated option call sites.

Priority: ⬇️ Low

Estimated code review effort: 4 (Complex) | ~45 minutes

Merge Risk: ⚪ Minimal · up to 66812

This change adds typed batch delete behavior and renames the backward-reference propagation option. The supplied coverage indicates the supported execution, validation, version-gating, and cost paths are covered, with no remaining concrete merge-blocking risk.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely identifies both primary changes: typed backward-reference delete operations and the option rename.
Docstring Coverage ✅ Passed Docstring coverage is 81.08% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 111 functions across 33 files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/grovedb-propagate-backward-refs-f5d2e0

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.

…ion it carries

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@codecov

codecov Bot commented Sep 9, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.05%. Comparing base (985ece6) to head (6681236).
⚠️ Report is 1 commits behind head on develop.

Additional details and impacted files
@@             Coverage Diff             @@
##           develop     #950      +/-   ##
===========================================
+ Coverage    92.99%   93.05%   +0.05%     
===========================================
  Files          327      330       +3     
  Lines       103297   103491     +194     
===========================================
+ Hits         96065    96303     +238     
+ Misses        7232     7188      -44     
Components Coverage Δ
grovedb-core 91.44% <100.00%> (+0.11%) ⬆️
merk 93.93% <ø> (ø)
storage 91.86% <ø> (ø)
commitment-tree 95.62% <ø> (ø)
mmr 95.11% <ø> (ø)
bulk-append-tree 92.78% <ø> (ø)
element 97.18% <ø> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

QuantumExplorer and others added 3 commits September 9, 2026 08:28
…per-op-mode branches

Codecov flagged the Debug labels of the two typed deletes, their _estimated_op
constructors, BatchApplyOptions::as_insert_options through
apply_operations_without_batching, the fresh-subtree pre-scan arms for Replace
and known-new tree writes under the flag, and the RefreshReference skip in
per-op mode. Each now has a test.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…atching path

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant