1use crate::error::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.conn.expect("transaction already consumed");
89 conn.commit_transaction().await
90 })
91 }
92
93 fn rollback(self: Box<Self>) -> Pin<Box<dyn Future<Output = EFResult<()>> + Send + 'static>> {
94 Box::pin(async move {
95 let mut conn = self.conn.expect("transaction already consumed");
96 conn.rollback_transaction().await
97 })
98 }
99
100 fn create_point<'a>(
101 &'a mut self,
102 name: &'a str,
103 ) -> Pin<Box<dyn Future<Output = EFResult<()>> + Send + 'a>> {
104 Box::pin(async move {
105 self.conn
106 .as_mut()
107 .ok_or_else(|| crate::error::EFError::transaction("transaction consumed"))?
108 .create_savepoint(name)
109 .await
110 })
111 }
112
113 fn release_point<'a>(
114 &'a mut self,
115 name: &'a str,
116 ) -> Pin<Box<dyn Future<Output = EFResult<()>> + Send + 'a>> {
117 Box::pin(async move {
118 self.conn
119 .as_mut()
120 .ok_or_else(|| crate::error::EFError::transaction("transaction consumed"))?
121 .release_savepoint(name)
122 .await
123 })
124 }
125
126 fn rollback_point<'a>(
127 &'a mut self,
128 name: &'a str,
129 ) -> Pin<Box<dyn Future<Output = EFResult<()>> + Send + 'a>> {
130 Box::pin(async move {
131 self.conn
132 .as_mut()
133 .ok_or_else(|| crate::error::EFError::transaction("transaction consumed"))?
134 .rollback_to_savepoint(name)
135 .await
136 })
137 }
138
139 fn set_isolation<'a>(
140 &'a mut self,
141 level: IsolationLevel,
142 ) -> Pin<Box<dyn Future<Output = EFResult<()>> + Send + 'a>> {
143 Box::pin(async move {
144 self.conn
145 .as_mut()
146 .ok_or_else(|| crate::error::EFError::transaction("transaction consumed"))?
147 .set_transaction_isolation(level)
148 .await
149 })
150 }
151
152 fn connection(&mut self) -> &mut (dyn IAsyncConnection + Send) {
153 self.conn
154 .as_mut()
155 .expect("transaction already consumed")
156 .as_mut()
157 }
158}