text_document_common/database/
transactions.rs1use crate::database::db_context::DbContext;
4use anyhow::{Ok, Result, bail};
5use redb::{ReadTransaction, ReadableDatabase, WriteTransaction};
6
7use crate::types;
8
9enum TransactionType {
10 Read(Option<Box<ReadTransaction>>),
11 Write(Option<Box<WriteTransaction>>),
12}
13
14pub struct Transaction {
15 transaction: TransactionType,
16}
17
18impl Transaction {
19 pub fn begin_write_transaction(db_context: &DbContext) -> Result<Transaction> {
20 let transaction = db_context.get_database().begin_write()?;
21 Ok(Transaction {
22 transaction: TransactionType::Write(Some(Box::from(transaction))),
23 })
24 }
25
26 pub fn begin_read_transaction(db_context: &DbContext) -> Result<Transaction> {
27 let transaction = db_context.get_database().begin_read()?;
28 Ok(Transaction {
29 transaction: TransactionType::Read(Some(Box::from(transaction))),
30 })
31 }
32 pub fn commit(&mut self) -> Result<()> {
33 match &mut self.transaction {
34 TransactionType::Read(_) => bail!("Cannot commit a read transaction"),
35 TransactionType::Write(transaction_option) => {
36 transaction_option.take().unwrap().commit()
37 }
38 }?;
39 Ok(())
40 }
41
42 pub fn rollback(&mut self) -> Result<()> {
43 match &mut self.transaction {
44 TransactionType::Read(_) => bail!("Cannot rollback a read transaction"),
45 TransactionType::Write(transaction_option) => {
46 transaction_option.take().unwrap().abort()
47 }
48 }?;
49 Ok(())
50 }
51
52 pub fn end_read_transaction(&mut self) -> Result<()> {
53 match &mut self.transaction {
54 TransactionType::Read(transaction_option) => {
55 transaction_option.take().unwrap().close()?;
56 Ok(())
57 }
58 TransactionType::Write(_) => bail!("Cannot end a write transaction as read"),
59 }
60 }
61
62 pub(crate) fn get_read_transaction(&self) -> &ReadTransaction {
63 match &self.transaction {
64 TransactionType::Read(Some(transaction)) => transaction,
65 _ => panic!("Transaction is not a read transaction"),
66 }
67 }
68
69 pub(crate) fn get_write_transaction(&self) -> &WriteTransaction {
70 match &self.transaction {
71 TransactionType::Write(Some(transaction)) => transaction,
72 _ => panic!("Transaction is not a write transaction"),
73 }
74 }
75
76 pub fn create_savepoint(&self) -> Result<types::Savepoint> {
77 match &self.transaction {
78 TransactionType::Read(_) => bail!("Cannot create savepoint on a read transaction"),
79 TransactionType::Write(transaction_option) => Ok(transaction_option
80 .as_ref()
81 .unwrap()
82 .persistent_savepoint()?),
83 }
84 }
85 pub fn restore_to_savepoint(&mut self, savepoint: types::Savepoint) -> Result<()> {
86 match &mut self.transaction {
87 TransactionType::Read(_) => bail!("Cannot restore savepoint on a read transaction"),
88 TransactionType::Write(transaction_option) => {
89 if let Some(mut transaction) = transaction_option.take() {
90 let redb_savepoint = transaction.get_persistent_savepoint(savepoint)?;
91 transaction.restore_savepoint(&redb_savepoint)?;
92 *transaction_option = Some(transaction);
93 Ok(())
94 } else {
95 bail!("Write transaction is not available")
96 }
97 }
98 }
99 }
100}