Skip to main content

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//! There are THREE transaction manager implementations in SochDB. Here's when to use each:
26//!
27//! ### 1. `MvccTransactionManager` (wal_integration.rs) - **RECOMMENDED FOR PRODUCTION**
28//!
29//! Full-featured transaction manager with:
30//! - ✅ WAL-based durability (fsync on commit)
31//! - ✅ MVCC snapshot isolation
32//! - ✅ Serializable Snapshot Isolation (SSI)
33//! - ✅ Group commit for high throughput
34//! - ✅ Version chains with garbage collection
35//!
36//! ```ignore
37//! use sochdb_storage::wal_integration::MvccTransactionManager;
38//!
39//! let txm = MvccTransactionManager::new("wal.log", |key, value| {
40//!     // Apply callback
41//!     Ok(())
42//! })?;
43//!
44//! let txn_id = txm.begin(IsolationLevel::Serializable)?;
45//! txm.write(txn_id, b"key", b"value")?;
46//! txm.commit(txn_id)?; // fsync guarantee
47//! ```
48//!
49//! ### 2. `MvccManager` (durable_storage.rs) - SSI VALIDATION ONLY
50//!
51//! Provides SSI conflict detection but delegates durability to storage layer.
52//! Used internally by `DurableStorage` for transaction tracking.
53//!
54//! - ✅ SSI rw-antidependency detection
55//! - ✅ Bloom filter optimization for read/write sets
56//! - ❌ No WAL (relies on caller for durability)
57//!
58//! ### 3. `TransactionManager` (mvcc_snapshot.rs) - **DEPRECATED FOR NEW CODE**
59//!
60//! Minimal snapshot isolation without durability. Only suitable for:
61//! - Unit testing
62//! - Ephemeral in-memory operations
63//!
64//! **Do not use 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}