use std::future::Future; use std::pin::Pin; use sqlx::{PgPool, Postgres, Transaction}; use crate::error::DurableError; pub type PgTx<'a> = Transaction<'a, Postgres>; pub type BoxFuture<'a, T> = Pin + Send + 'a>>; pub async fn with_transaction(pool: &PgPool, work: F) -> Result where F: for<'c> FnOnce(&'c mut PgTx<'_>) -> BoxFuture<'c, Result>, { let mut tx = pool.begin().await?; match work(&mut tx).await { Ok(value) => { tx.commit().await?; Ok(value) } Err(error) => { let _ = tx.rollback().await; Err(error) } } } /// Bound how long this transaction waits for row or advisory locks. pub async fn set_lock_timeout(tx: &mut PgTx<'_>) -> Result<(), DurableError> { sqlx::query("SET LOCAL lock_timeout = '5s'") .execute(tx.as_mut()) .await?; Ok(()) } pub async fn advisory_xact_lock(tx: &mut PgTx<'_>, key: i64) -> Result<(), DurableError> { sqlx::query("SELECT pg_advisory_xact_lock($1)") .bind(key) .execute(tx.as_mut()) .await?; Ok(()) }