sochdb_storage/transaction.rs
1// Copyright 2025 Sushanth (https://github.com/sushanthpy)
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Unified Transaction Coordinator
16//!
17//! This module defines the canonical transaction management interface for SochDB.
18//! It consolidates the functionality of multiple transaction managers:
19//!
20//! ## Implementation Guide
21//!
22//! There are THREE transaction manager implementations in SochDB. Here's when to use each:
23//!
24//! ### 1. `MvccTransactionManager` (wal_integration.rs) - **RECOMMENDED FOR PRODUCTION**
25//!
26//! Full-featured transaction manager with:
27//! - ✅ WAL-based durability (fsync on commit)
28//! - ✅ MVCC snapshot isolation
29//! - ✅ Serializable Snapshot Isolation (SSI)
30//! - ✅ Group commit for high throughput
31//! - ✅ Version chains with garbage collection
32//!
33//! ```ignore
34//! use sochdb_storage::wal_integration::MvccTransactionManager;
35//!
36//! let txm = MvccTransactionManager::new("wal.log", |key, value| {
37//! // Apply callback
38//! Ok(())
39//! })?;
40//!
41//! let txn_id = txm.begin(IsolationLevel::Serializable)?;
42//! txm.write(txn_id, b"key", b"value")?;
43//! txm.commit(txn_id)?; // fsync guarantee
44//! ```
45//!
46//! ### 2. `MvccManager` (durable_storage.rs) - SSI VALIDATION ONLY
47//!
48//! Provides SSI conflict detection but delegates durability to storage layer.
49//! Used internally by `DurableStorage` for transaction tracking.
50//!
51//! - ✅ SSI rw-antidependency detection
52//! - ✅ Bloom filter optimization for read/write sets
53//! - ❌ No WAL (relies on caller for durability)
54//!
55//! ### 3. `TransactionManager` (mvcc_snapshot.rs) - **DEPRECATED FOR NEW CODE**
56//!
57//! Minimal snapshot isolation without durability. Only suitable for:
58//! - Unit testing
59//! - Ephemeral in-memory operations
60//!
61//! **Do not use for production workloads requiring crash recovery.**
62//!
63//! ## Transaction Coordinator Trait
64//!
65//! The `TransactionCoordinator` trait unifies the common interface:
66
67use sochdb_core::Result;
68
69// Re-export TransactionMode from durable_storage (canonical definition)
70pub use crate::durable_storage::TransactionMode;
71
72/// Isolation level for transactions
73#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
74pub enum IsolationLevel {
75 /// Read committed - see all committed data
76 ReadCommitted,
77 /// Snapshot isolation (default) - consistent point-in-time view
78 #[default]
79 SnapshotIsolation,
80 /// Serializable via SSI - full serializability guarantee
81 Serializable,
82}
83
84/// Transaction handle returned by begin operations
85#[derive(Debug, Clone)]
86pub struct TransactionHandle {
87 /// Unique transaction ID
88 pub txn_id: u64,
89 /// Snapshot timestamp for MVCC visibility
90 pub snapshot_ts: u64,
91 /// Transaction mode
92 pub mode: TransactionMode,
93 /// Isolation level
94 pub isolation_level: IsolationLevel,
95}
96
97/// Unified transaction coordinator interface
98///
99/// This trait defines the canonical API for transaction management.
100/// All new transaction manager implementations should implement this trait.
101///
102/// ## Durability Contract
103///
104/// Implementations MUST document their durability guarantees:
105/// - `Durable`: Committed transactions survive crash (WAL + fsync)
106/// - `Ephemeral`: No durability guarantee (in-memory only)
107pub trait TransactionCoordinator: Send + Sync {
108 /// Begin a new transaction with default isolation level
109 fn begin(&self) -> Result<TransactionHandle>;
110
111 /// Begin a transaction with specified isolation level
112 fn begin_with_isolation(&self, isolation: IsolationLevel) -> Result<TransactionHandle>;
113
114 /// Begin a transaction with specified mode (for optimization)
115 fn begin_with_mode(&self, mode: TransactionMode) -> Result<TransactionHandle>;
116
117 /// Commit a transaction
118 ///
119 /// For durable implementations, this includes fsync.
120 /// Returns the commit timestamp on success.
121 fn commit(&self, txn_id: u64) -> Result<u64>;
122
123 /// Abort a transaction
124 ///
125 /// Discards all changes made by the transaction.
126 fn abort(&self, txn_id: u64) -> Result<()>;
127
128 /// Get the current snapshot timestamp for a transaction
129 fn get_snapshot_ts(&self, txn_id: u64) -> Option<u64>;
130
131 /// Check if a transaction is still active
132 fn is_active(&self, txn_id: u64) -> bool;
133
134 /// Record a read for SSI tracking
135 fn record_read(&self, txn_id: u64, key: &[u8]);
136
137 /// Record a write for SSI tracking
138 fn record_write(&self, txn_id: u64, key: &[u8]);
139
140 /// Get durability guarantee of this implementation
141 fn durability(&self) -> DurabilityLevel;
142}
143
144/// Durability guarantee level
145#[derive(Debug, Clone, Copy, PartialEq, Eq)]
146pub enum DurabilityLevel {
147 /// Fully durable with WAL + fsync
148 Durable,
149 /// Group commit (durable after batch fsync)
150 GroupCommit,
151 /// No durability (in-memory only)
152 Ephemeral,
153}
154
155/// Recovery statistics returned after crash recovery
156#[derive(Debug, Clone, Default)]
157pub struct RecoveryStats {
158 /// Number of transactions recovered
159 pub transactions_recovered: usize,
160 /// Number of individual writes recovered
161 pub writes_recovered: usize,
162 /// The commit timestamp after recovery
163 pub commit_ts: u64,
164}
165
166// =============================================================================
167// Re-exports for convenience
168// =============================================================================
169
170// Note: The canonical implementation is MvccTransactionManager from wal_integration
171// pub use crate::wal_integration::MvccTransactionManager;
172
173#[cfg(test)]
174mod tests {
175 use super::*;
176
177 #[test]
178 fn test_transaction_mode_tracking() {
179 assert!(TransactionMode::ReadWrite.tracks_reads());
180 assert!(TransactionMode::ReadWrite.tracks_writes());
181
182 assert!(!TransactionMode::ReadOnly.tracks_reads());
183 assert!(!TransactionMode::ReadOnly.tracks_writes());
184
185 assert!(!TransactionMode::WriteOnly.tracks_reads());
186 assert!(TransactionMode::WriteOnly.tracks_writes());
187 }
188
189 #[test]
190 fn test_isolation_level_default() {
191 assert_eq!(IsolationLevel::default(), IsolationLevel::SnapshotIsolation);
192 }
193}