use diesel::connection::AnsiTransactionManager;
use diesel::SqliteConnection;
use scoped_futures::ScopedBoxFuture;
use crate::sync_connection_wrapper::SyncTransactionManagerWrapper;
use crate::TransactionManager;
use super::SyncConnectionWrapper;
impl SyncConnectionWrapper<SqliteConnection> {
pub async fn immediate_transaction<'a, R, E, F>(&mut self, f: F) -> Result<R, E>
where
F: for<'r> FnOnce(&'r mut Self) -> ScopedBoxFuture<'a, 'r, Result<R, E>> + Send + 'a,
E: From<diesel::result::Error> + Send + 'a,
R: Send + 'a,
{
self.transaction_sql(f, "BEGIN IMMEDIATE").await
}
pub async fn exclusive_transaction<'a, R, E, F>(&mut self, f: F) -> Result<R, E>
where
F: for<'r> FnOnce(&'r mut Self) -> ScopedBoxFuture<'a, 'r, Result<R, E>> + Send + 'a,
E: From<diesel::result::Error> + Send + 'a,
R: Send + 'a,
{
self.transaction_sql(f, "BEGIN EXCLUSIVE").await
}
async fn transaction_sql<'a, R, E, F>(&mut self, f: F, sql: &'static str) -> Result<R, E>
where
F: for<'r> FnOnce(&'r mut Self) -> ScopedBoxFuture<'a, 'r, Result<R, E>> + Send + 'a,
E: From<diesel::result::Error> + Send + 'a,
R: Send + 'a,
{
self.spawn_blocking(|conn| AnsiTransactionManager::begin_transaction_sql(conn, sql))
.await?;
match f(&mut *self).await {
Ok(value) => {
SyncTransactionManagerWrapper::<AnsiTransactionManager>::commit_transaction(
&mut *self,
)
.await?;
Ok(value)
}
Err(e) => {
SyncTransactionManagerWrapper::<AnsiTransactionManager>::rollback_transaction(
&mut *self,
)
.await?;
Err(e)
}
}
}
}