use crate::{Result, TenantContext};
use sqlx::{Acquire, PgConnection, PgPool, Postgres, Transaction};
pub struct TenantDatabase<'a> {
tx: Transaction<'a, Postgres>,
tenant_context: TenantContext,
}
impl<'a> std::fmt::Debug for TenantDatabase<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("TenantDatabase")
.field("tenant_context", &self.tenant_context)
.finish_non_exhaustive()
}
}
impl<'a> TenantDatabase<'a> {
pub async fn begin(
pool: &PgPool,
tenant_context: &TenantContext,
) -> Result<TenantDatabase<'static>> {
let mut tx = pool.begin().await?;
sqlx::query("SELECT set_config('app.current_tenant_id', $1, true)")
.bind(tenant_context.tenant_id.to_string())
.execute(&mut *tx)
.await?;
Ok(TenantDatabase {
tx,
tenant_context: tenant_context.clone(),
})
}
pub async fn begin_from_connection(
conn: &'a mut PgConnection,
tenant_context: &TenantContext,
) -> Result<TenantDatabase<'a>> {
let mut tx = conn.begin().await?;
sqlx::query("SELECT set_config('app.current_tenant_id', $1, true)")
.bind(tenant_context.tenant_id.to_string())
.execute(&mut *tx)
.await?;
Ok(TenantDatabase {
tx,
tenant_context: tenant_context.clone(),
})
}
pub fn connection(&mut self) -> &mut PgConnection {
&mut self.tx
}
pub fn tenant_context(&self) -> &TenantContext {
&self.tenant_context
}
pub async fn commit(self) -> Result<()> {
self.tx.commit().await?;
Ok(())
}
pub async fn rollback(self) -> Result<()> {
self.tx.rollback().await?;
Ok(())
}
}