use std::future::Future;
use deadpool_postgres::{Client, Pool};
use futures::future::BoxFuture;
use crate::error::ForceSyncError;
#[derive(Clone, Debug)]
pub struct PgStore {
pool: Pool,
}
impl PgStore {
#[must_use]
pub const fn new(pool: Pool) -> Self {
Self { pool }
}
#[must_use]
pub const fn pool(&self) -> &Pool {
&self.pool
}
pub async fn with_client<T, F, Fut>(&self, f: F) -> Result<T, ForceSyncError>
where
F: FnOnce(Client) -> Fut,
Fut: Future<Output = Result<T, tokio_postgres::Error>>,
{
let client = self.pool.get().await?;
f(client).await.map_err(Into::into)
}
pub async fn with_transaction<T, F>(&self, f: F) -> Result<T, ForceSyncError>
where
F: for<'a> FnOnce(
&'a tokio_postgres::Transaction<'a>,
) -> BoxFuture<'a, Result<T, ForceSyncError>>,
{
let mut client = self.pool.get().await?;
let transaction = client.transaction().await?;
match f(&transaction).await {
Ok(value) => {
transaction.commit().await?;
Ok(value)
}
Err(err) => match transaction.rollback().await {
Ok(()) => Err(err),
Err(rollback) => Err(ForceSyncError::TransactionRollback {
callback: Box::new(err),
rollback,
}),
},
}
}
}