ferriorm_runtime/
transaction.rs1use crate::client::DatabaseClient;
9use crate::error::FerriormError;
10
11pub async fn run_transaction<F, Fut, T>(client: &DatabaseClient, f: F) -> Result<T, FerriormError>
26where
27 F: FnOnce(TransactionClient) -> Fut,
28 Fut: std::future::Future<Output = Result<(T, TransactionClient), FerriormError>>,
29{
30 match client {
31 #[cfg(feature = "postgres")]
32 DatabaseClient::Postgres(pool) => {
33 let tx = pool.begin().await?;
34 let tx_client = TransactionClient::Postgres(tx);
35 match f(tx_client).await {
36 Ok((result, tx_client)) => {
37 tx_client.commit().await?;
38 Ok(result)
39 }
40 Err(e) => {
41 Err(e)
43 }
44 }
45 }
46 #[cfg(feature = "sqlite")]
47 DatabaseClient::Sqlite(pool) => {
48 let tx = pool.begin().await?;
49 let tx_client = TransactionClient::Sqlite(tx);
50 match f(tx_client).await {
51 Ok((result, tx_client)) => {
52 tx_client.commit().await?;
53 Ok(result)
54 }
55 Err(e) => {
56 Err(e)
58 }
59 }
60 }
61 }
62}
63
64pub enum TransactionClient {
66 #[cfg(feature = "postgres")]
67 Postgres(sqlx::Transaction<'static, sqlx::Postgres>),
68 #[cfg(feature = "sqlite")]
69 Sqlite(sqlx::Transaction<'static, sqlx::Sqlite>),
70}
71
72impl TransactionClient {
73 pub async fn commit(self) -> Result<(), FerriormError> {
75 match self {
76 #[cfg(feature = "postgres")]
77 Self::Postgres(tx) => tx.commit().await.map_err(FerriormError::from),
78 #[cfg(feature = "sqlite")]
79 Self::Sqlite(tx) => tx.commit().await.map_err(FerriormError::from),
80 }
81 }
82
83 pub async fn rollback(self) -> Result<(), FerriormError> {
85 match self {
86 #[cfg(feature = "postgres")]
87 Self::Postgres(tx) => tx.rollback().await.map_err(FerriormError::from),
88 #[cfg(feature = "sqlite")]
89 Self::Sqlite(tx) => tx.rollback().await.map_err(FerriormError::from),
90 }
91 }
92}