use burncloud_database_core::error::{DatabaseResult, DatabaseError};
use burncloud_database_core::DatabaseConfig;
use crate::{DatabaseClient, DatabaseClientFactory};
use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::RwLock;
pub struct DatabasePool {
clients: Arc<RwLock<HashMap<String, Arc<DatabaseClient>>>>,
config: DatabaseConfig,
max_connections: usize,
}
impl DatabasePool {
pub fn new(config: DatabaseConfig, max_connections: usize) -> Self {
Self {
clients: Arc::new(RwLock::new(HashMap::new())),
config,
max_connections,
}
}
pub async fn get_client(&self, client_id: Option<&str>) -> DatabaseResult<Arc<DatabaseClient>> {
let key = client_id.unwrap_or("default").to_string();
{
let clients = self.clients.read().await;
if let Some(client) = clients.get(&key) {
if client.is_connected().await {
return Ok(client.clone());
}
}
}
let mut clients = self.clients.write().await;
if clients.len() >= self.max_connections {
return Err(DatabaseError::ConnectionFailed(
"Connection pool limit reached".to_string()
));
}
let connection = DatabaseClientFactory::create_connection(&self.config)?;
let query_executor = DatabaseClientFactory::create_query_executor(&self.config)?;
let client = Arc::new(DatabaseClient::new(
connection,
query_executor,
));
client.connect().await?;
clients.insert(key.clone(), client.clone());
Ok(client)
}
pub async fn remove_client(&self, client_id: &str) -> DatabaseResult<()> {
let mut clients = self.clients.write().await;
if let Some(client) = clients.remove(client_id) {
client.disconnect().await?;
}
Ok(())
}
pub async fn disconnect_all(&self) -> DatabaseResult<()> {
let mut clients = self.clients.write().await;
for (_, client) in clients.drain() {
let _ = client.disconnect().await;
}
Ok(())
}
pub async fn get_pool_size(&self) -> usize {
let clients = self.clients.read().await;
clients.len()
}
}