sochdb_storage/transaction.rs
1// SPDX-License-Identifier: AGPL-3.0-or-later
2// SochDB - LLM-Optimized Embedded Database
3// Copyright (C) 2026 Sushanth Reddy Vanagala (https://github.com/sushanthpy)
4//
5// This program is free software: you can redistribute it and/or modify
6// it under the terms of the GNU Affero General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU Affero General Public License for more details.
14//
15// You should have received a copy of the GNU Affero General Public License
16// along with this program. If not, see <https://www.gnu.org/licenses/>.
17
18//! Unified Transaction Coordinator
19//!
20//! This module defines the canonical transaction management interface for SochDB.
21//! It consolidates the functionality of multiple transaction managers:
22//!
23//! ## Implementation Guide
24//!
25//! **The live concurrency contract is multi-reader, single-writer.** Production
26//! isolation and durability run through `DurableStorage` (`database.rs` /
27//! `durable_storage.rs`): lock-free MVCC snapshot reads via `ConcurrentMvcc`,
28//! writes serialized by a single-writer lock (`acquire_writer`, "serialize WAL
29//! commits across processes"), and SSI conflict validation via `MvccManager`.
30//! WAL crash recovery is wired here (`txn_wal` / `RecoveryStats` /
31//! `durability_contract`). There is **no concurrent-writer (wired SSI) path on
32//! the live engine** — do not assume one exists.
33//!
34//! SochDB contains three transaction-manager types; only the first is on the
35//! live path:
36//!
37//! ### 1. `DurableStorage` + `MvccManager` (durable_storage.rs) — LIVE / PRODUCTION
38//!
39//! The actual production path. Single-writer write coordination + MVCC snapshot
40//! reads, with `MvccManager` providing SSI rw-antidependency validation and the
41//! storage layer providing WAL durability and crash recovery.
42//!
43//! ### 2. `MvccTransactionManager` (wal_integration.rs) — STANDALONE, NOT WIRED
44//!
45//! A complete, self-contained manager (WAL durability, MVCC snapshot isolation,
46//! optional SSI, group commit, version-chain GC). Despite being feature-rich it
47//! has **no functional caller in the engine** — `DurableStorage` does not use
48//! it — so it is **not** the production path. Use it only if you explicitly
49//! construct and own one; it does not participate in the live database's
50//! single-writer concurrency contract. (Its SSI read/write tracking is correct
51//! as of the Task 1B id-divergence fix, but it remains unwired.)
52//!
53//! ```ignore
54//! use sochdb_storage::wal_integration::MvccTransactionManager;
55//! let txm = MvccTransactionManager::new("wal.log", |_key, _value| Ok(()))?;
56//! let txn_id = txm.begin(IsolationLevel::Serializable)?;
57//! txm.write(txn_id, b"key", b"value")?;
58//! txm.commit(txn_id)?;
59//! ```
60//!
61//! ### 3. `TransactionManager` (mvcc_snapshot.rs) — `#[deprecated]`
62//!
63//! Minimal snapshot isolation without durability. Unit tests / ephemeral
64//! in-memory only. **Not for production workloads requiring crash recovery.**
65//!
66//! ## Transaction Coordinator Trait
67//!
68//! The `TransactionCoordinator` trait unifies the common interface:
69
70use sochdb_core::Result;
71
72// Re-export TransactionMode from durable_storage (canonical definition)
73pub use crate::durable_storage::TransactionMode;
74
75/// Isolation level for transactions
76#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
77pub enum IsolationLevel {
78 /// Read committed - see all committed data
79 ReadCommitted,
80 /// Snapshot isolation (default) - consistent point-in-time view
81 #[default]
82 SnapshotIsolation,
83 /// Serializable via SSI - full serializability guarantee
84 Serializable,
85}
86
87/// Transaction handle returned by begin operations
88#[derive(Debug, Clone)]
89pub struct TransactionHandle {
90 /// Unique transaction ID
91 pub txn_id: u64,
92 /// Snapshot timestamp for MVCC visibility
93 pub snapshot_ts: u64,
94 /// Transaction mode
95 pub mode: TransactionMode,
96 /// Isolation level
97 pub isolation_level: IsolationLevel,
98}
99
100/// Unified transaction coordinator interface
101///
102/// This trait defines the canonical API for transaction management.
103/// All new transaction manager implementations should implement this trait.
104///
105/// ## Durability Contract
106///
107/// Implementations MUST document their durability guarantees:
108/// - `Durable`: Committed transactions survive crash (WAL + fsync)
109/// - `Ephemeral`: No durability guarantee (in-memory only)
110pub trait TransactionCoordinator: Send + Sync {
111 /// Begin a new transaction with default isolation level
112 fn begin(&self) -> Result<TransactionHandle>;
113
114 /// Begin a transaction with specified isolation level
115 fn begin_with_isolation(&self, isolation: IsolationLevel) -> Result<TransactionHandle>;
116
117 /// Begin a transaction with specified mode (for optimization)
118 fn begin_with_mode(&self, mode: TransactionMode) -> Result<TransactionHandle>;
119
120 /// Commit a transaction
121 ///
122 /// For durable implementations, this includes fsync.
123 /// Returns the commit timestamp on success.
124 fn commit(&self, txn_id: u64) -> Result<u64>;
125
126 /// Abort a transaction
127 ///
128 /// Discards all changes made by the transaction.
129 fn abort(&self, txn_id: u64) -> Result<()>;
130
131 /// Get the current snapshot timestamp for a transaction
132 fn get_snapshot_ts(&self, txn_id: u64) -> Option<u64>;
133
134 /// Check if a transaction is still active
135 fn is_active(&self, txn_id: u64) -> bool;
136
137 /// Record a read for SSI tracking
138 fn record_read(&self, txn_id: u64, key: &[u8]);
139
140 /// Record a write for SSI tracking
141 fn record_write(&self, txn_id: u64, key: &[u8]);
142
143 /// Get durability guarantee of this implementation
144 fn durability(&self) -> DurabilityLevel;
145}
146
147/// Durability guarantee level
148#[derive(Debug, Clone, Copy, PartialEq, Eq)]
149pub enum DurabilityLevel {
150 /// Fully durable with WAL + fsync
151 Durable,
152 /// Group commit (durable after batch fsync)
153 GroupCommit,
154 /// No durability (in-memory only)
155 Ephemeral,
156}
157
158/// Recovery statistics returned after crash recovery
159#[derive(Debug, Clone, Default)]
160pub struct RecoveryStats {
161 /// Number of transactions recovered
162 pub transactions_recovered: usize,
163 /// Number of individual writes recovered
164 pub writes_recovered: usize,
165 /// The commit timestamp after recovery
166 pub commit_ts: u64,
167}
168
169// =============================================================================
170// Re-exports for convenience
171// =============================================================================
172
173// Note: The canonical implementation is MvccTransactionManager from wal_integration
174// pub use crate::wal_integration::MvccTransactionManager;
175
176#[cfg(test)]
177mod tests {
178 use super::*;
179
180 #[test]
181 fn test_transaction_mode_tracking() {
182 assert!(TransactionMode::ReadWrite.tracks_reads());
183 assert!(TransactionMode::ReadWrite.tracks_writes());
184
185 assert!(!TransactionMode::ReadOnly.tracks_reads());
186 assert!(!TransactionMode::ReadOnly.tracks_writes());
187
188 assert!(!TransactionMode::WriteOnly.tracks_reads());
189 assert!(TransactionMode::WriteOnly.tracks_writes());
190 }
191
192 #[test]
193 fn test_isolation_level_default() {
194 assert_eq!(IsolationLevel::default(), IsolationLevel::SnapshotIsolation);
195 }
196}