use std::time::Duration;
use sqlx::{AnyPool, any::AnyPoolOptions};
use super::lru_cache::LruCache;
use crate::connector::DbConnectorConfig;
use crate::errors::OrionError;
pub struct SqlPoolCache {
cache: LruCache<AnyPool>,
}
impl SqlPoolCache {
pub fn new(max_entries: usize) -> Self {
Self {
cache: LruCache::with_evict_handler(max_entries, "sql_pool", |pool: AnyPool| {
tokio::spawn(async move { pool.close().await });
}),
}
}
pub async fn get_pool(
&self,
connector_name: &str,
config: &DbConnectorConfig,
) -> Result<AnyPool, OrionError> {
let conn_str = config.connection_string.clone();
let max_conns = config.max_connections.unwrap_or(5);
let connect_timeout = config.connect_timeout_ms.unwrap_or(5000);
self.cache
.get_or_create(connector_name, || async move {
crate::validation::check_db_endpoint(connector_name, config).await?;
AnyPoolOptions::new()
.max_connections(max_conns)
.acquire_timeout(Duration::from_millis(connect_timeout))
.connect(&conn_str)
.await
.map_err(|e| OrionError::Internal {
context: format!("Failed to connect to external DB '{connector_name}'"),
source: Some(Box::new(e)),
})
})
.await
}
pub async fn evict(&self, connector_name: &str) {
self.cache.evict(connector_name).await;
}
pub async fn evict_all(&self) {
self.cache.evict_all().await;
}
}
impl Default for SqlPoolCache {
fn default() -> Self {
Self::new(100)
}
}