use deadpool_postgres::{Config, Pool, Runtime};
use tokio_postgres::NoTls;
use std::sync::Arc;
use tokio::sync::Semaphore;
use tracing::info;
use crate::config::PoolConfig;
#[derive(Clone)]
pub struct GlobalPool {
inner: Pool,
config: PoolConfig,
semaphore: Arc<Semaphore>,
}
impl GlobalPool {
pub async fn new(config: PoolConfig) -> anyhow::Result<Self> {
info!("Initializing GlobalPool with max_connections={}", config.max_connections);
let pg_host = std::env::var("PG__HOST").unwrap_or_else(|_| "localhost".to_string());
let pg_port = std::env::var("PG__PORT")
.ok()
.and_then(|p| p.parse().ok())
.unwrap_or(5432);
let pg_db = std::env::var("PG__DB").unwrap_or_else(|_| "camera".to_string());
let pg_user = std::env::var("PG__USER").unwrap_or_else(|_| "postgres".to_string());
let pg_pass = std::env::var("PG__PASSWORD").unwrap_or_else(|_| "".to_string());
let mut pg_config = Config::new();
pg_config.host = Some(pg_host);
pg_config.port = Some(pg_port);
pg_config.dbname = Some(pg_db);
pg_config.user = Some(pg_user);
pg_config.password = Some(pg_pass);
let inner = pg_config.create_pool(Some(Runtime::Tokio1), NoTls)
.map_err(|e| anyhow::anyhow!("Failed to create pool: {}", e))?;
let semaphore = Arc::new(Semaphore::new(config.max_connections));
let pool = Self {
inner,
config,
semaphore,
};
info!("GlobalPool initialized successfully");
Ok(pool)
}
pub async fn get_connection(&self) -> Result<deadpool_postgres::Client, deadpool_postgres::PoolError> {
self.inner.get().await
}
pub async fn try_get_connection(&self) -> Option<deadpool_postgres::Client> {
(self.inner.get().await).ok()
}
pub fn is_full(&self) -> bool {
self.inner.status().available == 0
}
pub fn stats(&self) -> deadpool_postgres::Status {
self.inner.status()
}
pub fn config(&self) -> &PoolConfig {
&self.config
}
pub fn semaphore(&self) -> &Arc<Semaphore> {
&self.semaphore
}
}