Skip to content

refactor: implement private transaction and snapshot - #959

Merged
jiangzhe merged 2 commits into
mainfrom
private-trx
Aug 7, 2026
Merged

refactor: implement private transaction and snapshot#959
jiangzhe merged 2 commits into
mainfrom
private-trx

Conversation

@jiangzhe

@jiangzhe jiangzhe commented Aug 7, 2026

Copy link
Copy Markdown
Owner

Closes #958

Summary by CodeRabbit

  • New Features

    • Added safer catalog updates for creating and removing tables and indexes.
    • Added private snapshots to support reliable maintenance and cleanup operations.
    • Added improved transaction handling for DDL operations, including rollback and recovery support.
  • Bug Fixes

    • Improved panic handling and cleanup during maintenance and catalog changes.
    • Prevented invalid nested or non-DDL private transactions.
    • Strengthened redo tracking and duplicate detection for catalog operations.

@jiangzhe jiangzhe self-assigned this Aug 7, 2026
@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Review was skipped due to path filters

⛔ Files ignored due to path filters (2)
  • docs/tasks/000262-private-transactions.md is excluded by none and included by none
  • docs/tasks/next-id is excluded by none and included by none

CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including **/dist/** will override the default block on the dist directory, by removing the pattern from both the lists.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro Plus

Run ID: 9984351f-85e4-4eef-b507-7a406c0f2ad1

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
📝 Walkthrough

Walkthrough

The change adds crate-private private transactions for catalog DDL, moves catalog staging into CatalogStorage, transfers DDL redo ownership to transactions, and migrates maintenance execution to runtime-owned scopes and private snapshots. Tests cover lifecycle, panic retention, rollback, redo installation, and snapshot cleanup.

Changes

Private transaction and runtime migration

Layer / File(s) Summary
Private transaction lifecycle
doradb-storage/src/trx/*, doradb-storage/src/session.rs
PrivateTransaction retains a checked-out core and attachment for DDL execution. Private transactions reject nested and non-DDL use. Statement cancellation, terminal ownership, cleanup, and DDL redo installation use transaction-level paths.
Maintenance execution and private snapshots
doradb-storage/src/table/gc.rs, doradb-storage/src/table/persistence.rs, doradb-storage/src/catalog/checkpoint.rs, doradb-storage/src/trx/retention.rs, doradb-storage/src/table/*
Maintenance executions own prepared scopes and receive SessionRuntime. Secondary MemIndex cleanup uses PrivateSnapshot, captures roots under the snapshot, releases snapshots before retry or completion, and reports phase diagnostics.
Catalog DDL staging and redo ownership
doradb-storage/src/catalog/storage/*, doradb-storage/src/trx/*
CatalogStorage stages table and index metadata through private transactions. Each staging operation validates catalog state and installs a transaction-level DDL redo marker. Test helpers record redo after transaction execution.
Table and index DDL integration
doradb-storage/src/catalog/table.rs, doradb-storage/src/catalog/index.rs, doradb-storage/src/recovery/mod.rs
CREATE and DROP table/index flows use private transactions, metadata snapshots, transaction parking during panic handling, direct catalog staging, and catalog-specific rollback.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant DDLExecution
  participant PrivateTransaction
  participant CatalogStorage
  participant CatalogTables
  participant Redo
  DDLExecution->>PrivateTransaction: begin private DDL transaction
  DDLExecution->>CatalogStorage: stage create or drop metadata
  CatalogStorage->>CatalogTables: stage catalog row mutations
  CatalogStorage->>Redo: install one transaction-level DDL redo marker
  DDLExecution->>PrivateTransaction: commit or rollback catalog DDL
Loading

Possibly related PRs

🚥 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 summarizes the main changes: introducing private transactions and snapshots.
Linked Issues check ✅ Passed The changes implement the linked issue objectives for private transactions, private snapshots, catalog staging, maintenance execution, and DDL redo handling.
Out of Scope Changes check ✅ Passed The reviewed changes are directly related to the linked issue and include supporting tests and transaction-state updates.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ 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 private-trx

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.

@codacy-production

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 5 medium

Results:
5 new issues

Category Results
Complexity 5 medium

View in Codacy

🟢 Metrics 63 complexity · 85 duplication

Metric Results
Complexity 63
Duplication 85

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@greptile-apps

greptile-apps Bot commented Aug 7, 2026

Copy link
Copy Markdown

Greptile Summary

The PR introduces strongly owned private transactions for catalog DDL and transaction-free registered snapshots for maintenance reads.

  • Moves catalog row staging into CatalogStorage and installs one transaction-level DDL redo marker after staging succeeds.
  • Retains private transaction ownership across DDL statements, with terminal conversion and synchronous panic parking.
  • Reworks secondary-index cleanup around lifetime-branded PrivateSnapshot registrations.
  • Makes maintenance execution objects own and release their resources before terminal or failed-retained publication.

Confidence Score: 5/5

The PR appears safe to merge because no blocking failure remains in the eligible follow-up review scope.

No blocking failure remains.

Important Files Changed

Filename Overview
doradb-storage/src/trx/mod.rs Adds the strongly attached private-transaction owner, retained checkout lifecycle, private statement settlement, and transaction-level DDL marker installation.
doradb-storage/src/trx/readonly.rs Adds registered private snapshots whose Drop implementation deregisters their STS from the active GC horizon.
doradb-storage/src/catalog/storage/ddl.rs Centralizes CREATE and DROP catalog staging into ordered per-logical-table statement boundaries.
doradb-storage/src/catalog/table.rs Migrates table DDL to private transactions and parks active transaction state before supervised panic retention.
doradb-storage/src/catalog/index.rs Migrates index DDL to private transactions and metadata-driven catalog staging while preserving rollback and panic handling.
doradb-storage/src/table/gc.rs Replaces cleanup transactions with fresh private snapshots for each root-capture attempt and releases registrations on retry, completion, and unwind.
doradb-storage/src/session.rs Refactors mandatory maintenance into stateful execution ownership and exposes private transaction creation only within accepted DDL.
doradb-storage/src/recovery/mod.rs Adapts recovery-side catalog transaction setup to the new transaction-level DDL redo representation.

Reviews (2): Last reviewed commit: "resolve task" | Re-trigger Greptile

@codecov

codecov Bot commented Aug 7, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.55096% with 54 lines in your changes missing coverage. Please review.
✅ Project coverage is 93.51%. Comparing base (b279d4f) to head (a7c1e06).

Files with missing lines Patch % Lines
doradb-storage/src/trx/mod.rs 93.26% 19 Missing ⚠️
doradb-storage/src/catalog/index.rs 60.00% 14 Missing ⚠️
doradb-storage/src/table/gc.rs 91.56% 7 Missing ⚠️
doradb-storage/src/catalog/storage/ddl.rs 97.85% 5 Missing ⚠️
doradb-storage/src/trx/retention.rs 77.77% 4 Missing ⚠️
doradb-storage/src/catalog/checkpoint.rs 75.00% 2 Missing ⚠️
doradb-storage/src/table/persistence.rs 88.88% 2 Missing ⚠️
doradb-storage/src/session.rs 98.68% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff            @@
##             main     #959    +/-   ##
========================================
  Coverage   93.51%   93.51%            
========================================
  Files         152      154     +2     
  Lines      131362   131555   +193     
========================================
+ Hits       122840   123022   +182     
- Misses       8522     8533    +11     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (5)
doradb-storage/src/catalog/storage/ddl.rs (1)

19-93: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider extracting catalog-row derivation into a helper.

stage_create_table mixes row derivation with statement staging. Static analysis reports 84 lines and cyclomatic complexity 14. Extract the four Vec builders into one private function that returns the derived rows. The staging body then reads as four boundaries plus one redo marker, and the derivation becomes unit-testable without a transaction.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@doradb-storage/src/catalog/storage/ddl.rs` around lines 19 - 93, Extract the
table, column, index, and index-column Vec construction from stage_create_table
into a private helper that returns all four derived row collections. Update
stage_create_table to call this helper, retain the existing four staging
boundaries and redo marker, and keep derivation independent of the transaction
so it can be unit-tested separately.

Source: Linters/SAST tools

doradb-storage/src/table/mod.rs (1)

1384-1388: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Update the stale assertion message after the hook rename.

The method and field are now install_cleanup_after_private_snapshot_hook and cleanup_after_private_snapshot_hook. The assertion still reports "MemIndex cleanup transaction-start hook already installed", which names the removed transaction-start concept.

♻️ Proposed fix
             assert!(
                 old.is_none(),
-                "MemIndex cleanup transaction-start hook already installed"
+                "MemIndex cleanup private-snapshot hook already installed"
             );
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@doradb-storage/src/table/mod.rs` around lines 1384 - 1388, Update the
assertion message in install_cleanup_after_private_snapshot_hook to describe the
cleanup-after-private-snapshot hook, replacing the stale MemIndex
transaction-start wording while preserving the existing assertion behavior.
doradb-storage/src/trx/stmt.rs (1)

340-353: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Reuse Statement::new in StmtState::statement.

StmtState::statement at lines 264-280 builds the same Statement literal with the same defaults. Call Statement::new there so the construction of a callback-facing statement stays in one place.

♻️ Proposed refactor
         let (inner, attachment) = checkout.inner_and_attachment_mut();
-        Statement {
-            inner,
-            attachment,
-            effects,
-            disable_dml_validation: false,
-        }
+        Statement::new(inner, attachment, effects)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@doradb-storage/src/trx/stmt.rs` around lines 340 - 353, Update
StmtState::statement to construct the callback-facing statement by calling
Statement::new with the existing inner, attachment, and effects references,
instead of duplicating the Statement literal and its defaults. Leave the
surrounding statement flow unchanged.
doradb-storage/src/table/gc.rs (1)

268-286: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Bind the registered snapshot once instead of re-reading it twice.

Lines 269-275 and 284-286 read execution.active_snapshot back with two unreachable panic! arms right after the assignment. Register into a local, read sts() from it, then move it into execution.active_snapshot, and borrow it once for the root capture. This removes both defensive panics without changing behavior.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@doradb-storage/src/table/gc.rs` around lines 268 - 286, Update the cleanup
loop to store the result of trx_sys.register_private_snapshot() in a local
variable, read its sts() before moving it into execution.active_snapshot, and
then borrow execution.active_snapshot once for root capture. Remove both
unwrap_or_else panic paths while preserving the existing snapshot registration
and scanning behavior.
doradb-storage/src/trx/mod.rs (1)

3551-3561: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Reuse the existing active-list length accessor.

active_sts_count recomputes the live count as active.len() - active.deleted.len(). ActiveStsList already exposes len(), which other code uses (for example in doradb-storage/src/trx/purge.rs tests). The manual subtraction duplicates that logic and panics on unsigned underflow if the two collections ever diverge.

♻️ Proposed refactor
     pub(crate) fn active_sts_count(trx_sys: &sys::TransactionSystem) -> usize {
         trx_sys
             .gc_buckets
             .iter()
-            .map(|bucket| {
-                let active_sts = bucket.active_sts_list.lock();
-                active_sts.active.len() - active_sts.deleted.len()
-            })
+            .map(|bucket| bucket.active_sts_list.lock().len())
             .sum()
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@doradb-storage/src/trx/mod.rs` around lines 3551 - 3561, Update
active_sts_count to call ActiveStsList::len() for each locked bucket instead of
manually subtracting active.deleted.len() from active.len(), preserving the
existing sum of live snapshot counts.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@doradb-storage/src/table/gc.rs`:
- Around line 287-295: Update the health-check error path around
execute_mem_index_cleanup_inner and execution.phase so an ensure_healthy failure
releases execution.active_snapshot and deregisters the associated STS before
returning. Set the execution state consistently with the existing explicit
release path, while preserving the current RuntimeOrFatalError conversion and
normal-path behavior.

---

Nitpick comments:
In `@doradb-storage/src/catalog/storage/ddl.rs`:
- Around line 19-93: Extract the table, column, index, and index-column Vec
construction from stage_create_table into a private helper that returns all four
derived row collections. Update stage_create_table to call this helper, retain
the existing four staging boundaries and redo marker, and keep derivation
independent of the transaction so it can be unit-tested separately.

In `@doradb-storage/src/table/gc.rs`:
- Around line 268-286: Update the cleanup loop to store the result of
trx_sys.register_private_snapshot() in a local variable, read its sts() before
moving it into execution.active_snapshot, and then borrow
execution.active_snapshot once for root capture. Remove both unwrap_or_else
panic paths while preserving the existing snapshot registration and scanning
behavior.

In `@doradb-storage/src/table/mod.rs`:
- Around line 1384-1388: Update the assertion message in
install_cleanup_after_private_snapshot_hook to describe the
cleanup-after-private-snapshot hook, replacing the stale MemIndex
transaction-start wording while preserving the existing assertion behavior.

In `@doradb-storage/src/trx/mod.rs`:
- Around line 3551-3561: Update active_sts_count to call ActiveStsList::len()
for each locked bucket instead of manually subtracting active.deleted.len() from
active.len(), preserving the existing sum of live snapshot counts.

In `@doradb-storage/src/trx/stmt.rs`:
- Around line 340-353: Update StmtState::statement to construct the
callback-facing statement by calling Statement::new with the existing inner,
attachment, and effects references, instead of duplicating the Statement literal
and its defaults. Leave the surrounding statement flow unchanged.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro Plus

Run ID: dea478d8-98de-4019-8376-f86680864733

📥 Commits

Reviewing files that changed from the base of the PR and between b279d4f and a7c1e06.

⛔ Files ignored due to path filters (5)
  • docs/garbage-collect.md is excluded by none and included by none
  • docs/lock-system.md is excluded by none and included by none
  • docs/tasks/000262-private-transactions.md is excluded by none and included by none
  • docs/transaction-system.md is excluded by none and included by none
  • docs/unsafe-usage-baseline.md is excluded by none and included by none
📒 Files selected for processing (21)
  • doradb-storage/src/catalog/checkpoint.rs
  • doradb-storage/src/catalog/index.rs
  • doradb-storage/src/catalog/storage/columns.rs
  • doradb-storage/src/catalog/storage/ddl.rs
  • doradb-storage/src/catalog/storage/indexes.rs
  • doradb-storage/src/catalog/storage/mod.rs
  • doradb-storage/src/catalog/storage/tables.rs
  • doradb-storage/src/catalog/table.rs
  • doradb-storage/src/recovery/mod.rs
  • doradb-storage/src/session.rs
  • doradb-storage/src/table/access.rs
  • doradb-storage/src/table/gc.rs
  • doradb-storage/src/table/mod.rs
  • doradb-storage/src/table/persistence.rs
  • doradb-storage/src/table/storage.rs
  • doradb-storage/src/trx/mod.rs
  • doradb-storage/src/trx/purge.rs
  • doradb-storage/src/trx/readonly.rs
  • doradb-storage/src/trx/retention.rs
  • doradb-storage/src/trx/stmt.rs
  • doradb-storage/src/trx/sys.rs

Comment thread doradb-storage/src/table/gc.rs
@jiangzhe
jiangzhe merged commit f4b2493 into main Aug 7, 2026
9 of 10 checks passed
@jiangzhe
jiangzhe deleted the private-trx branch August 7, 2026 14:53
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.

Task: Introduce Private Transactions for Catalog DDL and Maintenance

1 participant