use anyhow::{Context, Result};
use deadpool_postgres::Pool;
use fraiseql_db::postgres::{
PoolPrewarmConfig, PostgresAdapter, PostgresTlsConfig, VectorScanConfig,
};
use crate::schema::database_validator::refuse_removed_engine_url;
const CLI_POOL_SIZE: usize = 2;
pub fn require_postgres(db_url: &str) -> Result<()> {
refuse_removed_engine_url(db_url)?;
db_url.parse::<tokio_postgres::Config>().map_err(|e| {
anyhow::anyhow!(
"Not a PostgreSQL connection string ({e}). Pass a postgresql://… URL or a libpq \
`key=value` string such as `host=localhost dbname=app user=app`."
)
})?;
Ok(())
}
pub async fn postgres_pool(db_url: &str, purpose: &str, tls: &PostgresTlsConfig) -> Result<Pool> {
Ok(postgres_adapter(db_url, purpose, tls).await?.pool().clone())
}
pub async fn postgres_adapter(
db_url: &str,
purpose: &str,
tls: &PostgresTlsConfig,
) -> Result<PostgresAdapter> {
require_postgres(db_url)?;
PostgresAdapter::with_pool_config(
db_url,
PoolPrewarmConfig {
min_size: 0,
max_size: CLI_POOL_SIZE,
timeout_secs: None,
search_path: None,
tls: tls.clone(),
read_replicas: None,
max_streaming_reads: None,
vector_scan: VectorScanConfig::default(),
},
)
.await
.map_err(anyhow::Error::new)
.with_context(|| {
format!(
"failed to connect to PostgreSQL for {purpose} (ssl_mode = {})",
tls.effective_mode()
)
})
}
#[cfg(test)]
mod tests;