use crate::error::EFResult;
use crate::provider::{IAsyncConnection, IsolationLevel};
use std::future::Future;
use std::pin::Pin;
pub trait ITransaction: Send + Sync {
fn commit(self: Box<Self>) -> Pin<Box<dyn Future<Output = EFResult<()>> + Send + 'static>>;
fn rollback(self: Box<Self>) -> Pin<Box<dyn Future<Output = EFResult<()>> + Send + 'static>>;
fn create_point<'a>(
&'a mut self,
name: &'a str,
) -> Pin<Box<dyn Future<Output = EFResult<()>> + Send + 'a>>;
fn release_point<'a>(
&'a mut self,
name: &'a str,
) -> Pin<Box<dyn Future<Output = EFResult<()>> + Send + 'a>>;
fn rollback_point<'a>(
&'a mut self,
name: &'a str,
) -> Pin<Box<dyn Future<Output = EFResult<()>> + Send + 'a>>;
fn set_isolation<'a>(
&'a mut self,
level: IsolationLevel,
) -> Pin<Box<dyn Future<Output = EFResult<()>> + Send + 'a>>;
fn connection(&mut self) -> &mut (dyn IAsyncConnection + Send);
}
pub struct DbTransaction {
conn: Option<Box<dyn IAsyncConnection>>,
}
impl DbTransaction {
pub fn new(conn: Box<dyn IAsyncConnection>) -> Self {
Self { conn: Some(conn) }
}
}
impl ITransaction for DbTransaction {
fn commit(self: Box<Self>) -> Pin<Box<dyn Future<Output = EFResult<()>> + Send + 'static>> {
Box::pin(async move {
let mut conn = self.conn.expect("transaction already consumed");
conn.commit_transaction().await
})
}
fn rollback(self: Box<Self>) -> Pin<Box<dyn Future<Output = EFResult<()>> + Send + 'static>> {
Box::pin(async move {
let mut conn = self.conn.expect("transaction already consumed");
conn.rollback_transaction().await
})
}
fn create_point<'a>(
&'a mut self,
name: &'a str,
) -> Pin<Box<dyn Future<Output = EFResult<()>> + Send + 'a>> {
Box::pin(async move {
self.conn
.as_mut()
.ok_or_else(|| crate::error::EFError::transaction("transaction consumed"))?
.create_savepoint(name)
.await
})
}
fn release_point<'a>(
&'a mut self,
name: &'a str,
) -> Pin<Box<dyn Future<Output = EFResult<()>> + Send + 'a>> {
Box::pin(async move {
self.conn
.as_mut()
.ok_or_else(|| crate::error::EFError::transaction("transaction consumed"))?
.release_savepoint(name)
.await
})
}
fn rollback_point<'a>(
&'a mut self,
name: &'a str,
) -> Pin<Box<dyn Future<Output = EFResult<()>> + Send + 'a>> {
Box::pin(async move {
self.conn
.as_mut()
.ok_or_else(|| crate::error::EFError::transaction("transaction consumed"))?
.rollback_to_savepoint(name)
.await
})
}
fn set_isolation<'a>(
&'a mut self,
level: IsolationLevel,
) -> Pin<Box<dyn Future<Output = EFResult<()>> + Send + 'a>> {
Box::pin(async move {
self.conn
.as_mut()
.ok_or_else(|| crate::error::EFError::transaction("transaction consumed"))?
.set_transaction_isolation(level)
.await
})
}
fn connection(&mut self) -> &mut (dyn IAsyncConnection + Send) {
self.conn
.as_mut()
.expect("transaction already consumed")
.as_mut()
}
}