use std::future::Future;
use arcature_db::Db;
use arcature_db::sea_orm;
use arcature_db::sea_orm::TransactionTrait;
use arcature_db::sqlx;
use crate::error::DataError;
pub struct Transaction;
impl Transaction {
pub async fn orm<F, T>(db: &Db, f: F) -> Result<T, DataError>
where
F: for<'c> FnOnce(
&'c sea_orm::DatabaseTransaction,
) -> std::pin::Pin<
Box<dyn Future<Output = Result<T, sea_orm::DbErr>> + Send + 'c>,
> + Send,
T: Send,
{
let result = db.orm().transaction(f).await;
result.map_err(|error| {
let db_err = match error {
sea_orm::TransactionError::Connection(err) => err,
sea_orm::TransactionError::Transaction(err) => err,
};
DataError::from(db_err)
})
}
pub async fn sqlx<F, T>(db: &Db, f: F) -> Result<T, DataError>
where
F: for<'c> FnOnce(
&'c mut sqlx::Transaction<'_, sqlx::Postgres>,
) -> std::pin::Pin<
Box<dyn Future<Output = Result<T, sqlx::Error>> + Send + 'c>,
>,
T: Send,
{
let mut txn = db.sqlx().begin().await.map_err(DataError::from)?;
let result = f(&mut txn).await;
match result {
Ok(value) => {
txn.commit().await.map_err(DataError::from)?;
Ok(value)
}
Err(error) => {
drop(txn);
Err(DataError::from(error))
}
}
}
}