1use crate::error::{EFError, EFResult};
21use crate::provider::{IAsyncConnection, IsolationLevel};
22use std::future::Future;
23use std::pin::Pin;
24
25pub trait ITransaction: Send + Sync {
35 fn commit(self: Box<Self>) -> Pin<Box<dyn Future<Output = EFResult<()>> + Send + 'static>>;
37
38 fn rollback(self: Box<Self>) -> Pin<Box<dyn Future<Output = EFResult<()>> + Send + 'static>>;
40
41 fn create_point<'a>(
43 &'a mut self,
44 name: &'a str,
45 ) -> Pin<Box<dyn Future<Output = EFResult<()>> + Send + 'a>>;
46
47 fn release_point<'a>(
49 &'a mut self,
50 name: &'a str,
51 ) -> Pin<Box<dyn Future<Output = EFResult<()>> + Send + 'a>>;
52
53 fn rollback_point<'a>(
55 &'a mut self,
56 name: &'a str,
57 ) -> Pin<Box<dyn Future<Output = EFResult<()>> + Send + 'a>>;
58
59 fn set_isolation<'a>(
61 &'a mut self,
62 level: IsolationLevel,
63 ) -> Pin<Box<dyn Future<Output = EFResult<()>> + Send + 'a>>;
64
65 fn connection(&mut self) -> &mut (dyn IAsyncConnection + Send);
68}
69
70pub struct DbTransaction {
76 conn: Option<Box<dyn IAsyncConnection>>,
77}
78
79impl DbTransaction {
80 pub fn new(conn: Box<dyn IAsyncConnection>) -> Self {
81 Self { conn: Some(conn) }
82 }
83}
84
85impl ITransaction for DbTransaction {
86 fn commit(self: Box<Self>) -> Pin<Box<dyn Future<Output = EFResult<()>> + Send + 'static>> {
87 Box::pin(async move {
88 let mut conn = self
89 .conn
90 .ok_or_else(|| EFError::transaction("transaction already consumed"))?;
91 conn.commit_transaction().await
92 })
93 }
94
95 fn rollback(self: Box<Self>) -> Pin<Box<dyn Future<Output = EFResult<()>> + Send + 'static>> {
96 Box::pin(async move {
97 let mut conn = self
98 .conn
99 .ok_or_else(|| EFError::transaction("transaction already consumed"))?;
100 conn.rollback_transaction().await
101 })
102 }
103
104 fn create_point<'a>(
105 &'a mut self,
106 name: &'a str,
107 ) -> Pin<Box<dyn Future<Output = EFResult<()>> + Send + 'a>> {
108 Box::pin(async move {
109 self.conn
110 .as_mut()
111 .ok_or_else(|| crate::error::EFError::transaction("transaction consumed"))?
112 .create_savepoint(name)
113 .await
114 })
115 }
116
117 fn release_point<'a>(
118 &'a mut self,
119 name: &'a str,
120 ) -> Pin<Box<dyn Future<Output = EFResult<()>> + Send + 'a>> {
121 Box::pin(async move {
122 self.conn
123 .as_mut()
124 .ok_or_else(|| crate::error::EFError::transaction("transaction consumed"))?
125 .release_savepoint(name)
126 .await
127 })
128 }
129
130 fn rollback_point<'a>(
131 &'a mut self,
132 name: &'a str,
133 ) -> Pin<Box<dyn Future<Output = EFResult<()>> + Send + 'a>> {
134 Box::pin(async move {
135 self.conn
136 .as_mut()
137 .ok_or_else(|| crate::error::EFError::transaction("transaction consumed"))?
138 .rollback_to_savepoint(name)
139 .await
140 })
141 }
142
143 fn set_isolation<'a>(
144 &'a mut self,
145 level: IsolationLevel,
146 ) -> Pin<Box<dyn Future<Output = EFResult<()>> + Send + 'a>> {
147 Box::pin(async move {
148 self.conn
149 .as_mut()
150 .ok_or_else(|| crate::error::EFError::transaction("transaction consumed"))?
151 .set_transaction_isolation(level)
152 .await
153 })
154 }
155
156 fn connection(&mut self) -> &mut (dyn IAsyncConnection + Send) {
157 self.conn
158 .as_mut()
159 .expect("transaction already consumed")
160 .as_mut()
161 }
162}