Files
Oxicloud/src/infrastructure/repositories/pg/transaction_utils.rs
T

59 lines
2.1 KiB
Rust
Raw Normal View History

2026-02-14 01:29:34 +01:00
use sqlx::{Error as SqlxError, PgPool, Postgres, Transaction};
2025-04-09 00:21:20 +02:00
use std::sync::Arc;
use tracing::{debug, error, info};
/// Helper function to execute database operations in a transaction
/// Takes a database pool and a closure that will be executed within a transaction
/// The closure receives a transaction object that should be used for all database operations
/// If the closure returns an error, the transaction is rolled back
/// If the closure returns Ok, the transaction is committed
pub async fn with_transaction<F, T, E>(
pool: &Arc<PgPool>,
operation_name: &str,
operation: F,
) -> Result<T, E>
where
2026-02-14 01:29:34 +01:00
F: for<'c> FnOnce(
&'c mut Transaction<'_, Postgres>,
) -> futures::future::BoxFuture<'c, Result<T, E>>,
2025-04-09 00:21:20 +02:00
E: From<SqlxError> + std::fmt::Display,
{
debug!("Starting database transaction for: {}", operation_name);
2026-02-14 01:29:34 +01:00
2025-04-09 00:21:20 +02:00
// Begin transaction
let mut tx = pool.begin().await.map_err(|e| {
error!("Failed to begin transaction for {}: {}", operation_name, e);
E::from(e)
})?;
2026-02-14 01:29:34 +01:00
2025-04-09 00:21:20 +02:00
// Execute the operation within the transaction
match operation(&mut tx).await {
Ok(result) => {
// If operation succeeds, commit the transaction
match tx.commit().await {
Ok(_) => {
debug!("Transaction committed successfully for: {}", operation_name);
Ok(result)
2026-02-14 01:29:34 +01:00
}
2025-04-09 00:21:20 +02:00
Err(e) => {
error!("Failed to commit transaction for {}: {}", operation_name, e);
Err(E::from(e))
}
}
2026-02-14 01:29:34 +01:00
}
2025-04-09 00:21:20 +02:00
Err(e) => {
// If operation fails, rollback the transaction
if let Err(rollback_err) = tx.rollback().await {
2026-02-14 01:29:34 +01:00
error!(
"Failed to rollback transaction for {}: {}",
operation_name, rollback_err
);
2025-04-09 00:21:20 +02:00
// Still return the original error
} else {
info!("Transaction rolled back for {}: {}", operation_name, e);
}
Err(e)
}
}
2026-02-14 01:29:34 +01:00
}