use std::sync::OnceLock;
use std::time::Duration;
use noema::core::{Container, Injectable};
use sqlx::postgres::PgPoolOptions;
use crate::config::DatabaseConfig;
use crate::uow::Tx;
static POOL: OnceLock<sqlx::PgPool> = OnceLock::new();
#[derive(Clone)]
pub struct PgPool {
inner: sqlx::PgPool,
}
impl PgPool {
pub fn connection(&self) -> &sqlx::PgPool {
&self.inner
}
}
pub(crate) fn pool() -> &'static sqlx::PgPool {
POOL.get()
.expect("database pool not started; call Application::start")
}
pub async fn start(cfg: &DatabaseConfig) -> Result<(), sqlx::Error> {
if POOL.get().is_some() {
return Ok(());
}
let pool = PgPoolOptions::new()
.max_connections(cfg.max_connections)
.acquire_timeout(Duration::from_millis(u64::from(cfg.acquire_timeout_ms)))
.connect(&cfg.url)
.await?;
let _ = POOL.set(pool);
Ok(())
}
pub(crate) fn is_connected() -> bool {
POOL.get().is_some()
}
impl Injectable<Container> for PgPool {
fn inject(_: &Container) -> Self {
Self {
inner: pool().clone(),
}
}
}
pub fn postgres_tx(tx: &mut Tx) -> &mut sqlx::Transaction<'static, sqlx::Postgres> {
tx.inner_mut()
}
pub async fn ping() -> Result<(), sqlx::Error> {
sqlx::query("SELECT 1").execute(pool()).await?;
Ok(())
}