wasm_dbms/transaction/
session.rs1use std::collections::HashMap;
8
9use wasm_dbms_api::prelude::{DbmsError, DbmsResult, QueryError, TransactionId};
10
11use super::Transaction;
12
13#[derive(Default, Debug)]
15pub struct TransactionSession {
16 transactions: HashMap<TransactionId, Transaction>,
18 owners: HashMap<TransactionId, Vec<u8>>,
20 next_transaction_id: TransactionId,
22}
23
24impl TransactionSession {
25 pub fn begin_transaction(&mut self, owner: Vec<u8>) -> TransactionId {
27 let transaction_id = self.next_transaction_id;
28 self.next_transaction_id += 1;
29
30 self.transactions
31 .insert(transaction_id, Transaction::default());
32 self.owners.insert(transaction_id, owner);
33
34 transaction_id
35 }
36
37 pub fn has_transaction(&self, transaction_id: &TransactionId, caller: &[u8]) -> bool {
39 self.owners
40 .get(transaction_id)
41 .is_some_and(|owner| owner.as_slice() == caller)
42 }
43
44 pub fn get_transaction(&self, transaction_id: &TransactionId) -> DbmsResult<&Transaction> {
46 self.transactions
47 .get(transaction_id)
48 .ok_or(DbmsError::Query(QueryError::TransactionNotFound))
49 }
50
51 pub fn take_transaction(&mut self, transaction_id: &TransactionId) -> DbmsResult<Transaction> {
53 let transaction = self
54 .transactions
55 .remove(transaction_id)
56 .ok_or(DbmsError::Query(QueryError::TransactionNotFound))?;
57 self.owners.remove(transaction_id);
58
59 Ok(transaction)
60 }
61
62 pub fn close_transaction(&mut self, transaction_id: &TransactionId) {
64 self.transactions.remove(transaction_id);
65 self.owners.remove(transaction_id);
66 }
67
68 pub fn get_transaction_mut(
70 &mut self,
71 transaction_id: &TransactionId,
72 ) -> DbmsResult<&mut Transaction> {
73 self.transactions
74 .get_mut(transaction_id)
75 .ok_or(DbmsError::Query(QueryError::TransactionNotFound))
76 }
77}
78
79#[cfg(test)]
80mod tests {
81
82 use super::*;
83
84 #[test]
85 fn test_should_begin_transaction() {
86 let mut session = TransactionSession::default();
87 let alice = vec![1, 2, 3];
88 let bob = vec![4, 5, 6];
89 let transaction_id = session.begin_transaction(alice.clone());
90
91 assert!(session.has_transaction(&transaction_id, &alice));
92 assert!(!session.has_transaction(&transaction_id, &bob));
93
94 let transaction = session.get_transaction_mut(&transaction_id);
95 assert!(transaction.is_ok());
96 }
97
98 #[test]
99 fn test_should_close_transaction() {
100 let mut session = TransactionSession::default();
101 let alice = vec![1, 2, 3];
102 let transaction_id = session.begin_transaction(alice.clone());
103
104 assert!(session.has_transaction(&transaction_id, &alice));
105
106 session.close_transaction(&transaction_id);
107
108 assert!(!session.has_transaction(&transaction_id, &alice));
109 let transaction = session.get_transaction_mut(&transaction_id);
110 assert!(transaction.is_err());
111 assert!(!session.owners.contains_key(&transaction_id));
112 assert!(!session.transactions.contains_key(&transaction_id));
113 }
114
115 #[test]
116 fn test_should_take_transaction() {
117 let mut session = TransactionSession::default();
118 let alice = vec![1, 2, 3];
119 let transaction_id = session.begin_transaction(alice.clone());
120
121 let _transaction = session
122 .take_transaction(&transaction_id)
123 .expect("failed to take tx");
124
125 assert!(!session.has_transaction(&transaction_id, &alice));
126 let transaction_after_take = session.get_transaction(&transaction_id);
127 assert!(transaction_after_take.is_err());
128 assert!(!session.owners.contains_key(&transaction_id));
129 assert!(!session.transactions.contains_key(&transaction_id));
130 }
131
132 #[test]
133 fn test_should_get_transaction() {
134 let mut session = TransactionSession::default();
135 let alice = vec![1, 2, 3];
136 let transaction_id = session.begin_transaction(alice);
137
138 let _tx = session
139 .get_transaction(&transaction_id)
140 .expect("failed to get tx");
141 }
142}