use crate::db::database::{DatabaseConnection, DbError, ConnectionConfig};
use crate::utils::simple_pool::SimplePool;
use std::sync::Arc;
pub enum Pool {
SQLite(SimplePool<crate::db::sqlite::SqliteConnection>),
MySQL(SimplePool<crate::db::mysql::MySqlConnection>),
PostgreSQL(SimplePool<crate::db::postgresql::PostgresConnection>),
}
#[derive(Clone)]
pub struct PoolConfig {
pub max_size: usize,
pub min_idle: usize,
pub timeout: std::time::Duration,
pub max_lifetime: Option<std::time::Duration>,
pub idle_timeout: Option<std::time::Duration>,
}
impl Default for PoolConfig {
fn default() -> Self {
Self {
max_size: 10,
min_idle: 1,
timeout: std::time::Duration::from_secs(30),
max_lifetime: None,
idle_timeout: None,
}
}
}
impl Pool {
pub async fn sqlite(path: &str, config: PoolConfig) -> Result<Self, DbError> {
let mut connections = Vec::new();
for _ in 0..config.max_size {
let conn = crate::db::sqlite::SqliteConnection::new(path).await?;
connections.push(conn);
}
Ok(Pool::SQLite(SimplePool::new(connections)))
}
pub async fn mysql(config: &ConnectionConfig, pool_config: PoolConfig) -> Result<Self, DbError> {
let mut connections = Vec::new();
for _ in 0..pool_config.max_size {
let conn = crate::db::mysql::MySqlConnection::new(config).await?;
connections.push(conn);
}
Ok(Pool::MySQL(SimplePool::new(connections)))
}
pub async fn postgresql(config: &ConnectionConfig, pool_config: PoolConfig) -> Result<Self, DbError> {
let mut connections = Vec::new();
for _ in 0..pool_config.max_size {
let conn = crate::db::postgresql::PostgresConnection::new(config).await?;
connections.push(conn);
}
Ok(Pool::PostgreSQL(SimplePool::new(connections)))
}
pub async fn get_connection(&self) -> Result<Arc<dyn DatabaseConnection>, DbError> {
match self {
Pool::SQLite(pool) => {
let conn = pool.get().await
.map_err(|e| DbError::PoolError(e))?;
Ok(Arc::new(conn))
}
Pool::MySQL(pool) => {
let conn = pool.get().await
.map_err(|e| DbError::PoolError(e))?;
Ok(Arc::new(conn))
}
Pool::PostgreSQL(pool) => {
let conn = pool.get().await
.map_err(|e| DbError::PoolError(e))?;
Ok(Arc::new(conn))
}
}
}
pub async fn return_connection(&self, conn: Arc<dyn DatabaseConnection>) -> Result<(), DbError> {
match self {
Pool::SQLite(pool) => {
let _ = (pool, conn);
Ok(())
}
Pool::MySQL(pool) => {
let _ = (pool, conn);
Ok(())
}
Pool::PostgreSQL(pool) => {
let _ = (pool, conn);
Ok(())
}
}
}
pub fn status(&self) -> crate::utils::simple_pool::PoolStatus {
match self {
Pool::SQLite(pool) => pool.status(),
Pool::MySQL(pool) => pool.status(),
Pool::PostgreSQL(pool) => pool.status(),
}
}
pub fn size(&self) -> usize {
match self {
Pool::SQLite(pool) => pool.size(),
Pool::MySQL(pool) => pool.size(),
Pool::PostgreSQL(pool) => pool.size(),
}
}
pub async fn close(&self) -> Result<(), DbError> {
match self {
Pool::SQLite(pool) => {
for _ in 0..pool.size() {
if let Ok(conn) = pool.get().await {
conn.close().await?;
}
}
}
Pool::MySQL(pool) => {
for _ in 0..pool.size() {
if let Ok(conn) = pool.get().await {
conn.close().await?;
}
}
}
Pool::PostgreSQL(pool) => {
for _ in 0..pool.size() {
if let Ok(conn) = pool.get().await {
conn.close().await?;
}
}
}
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_sqlite_pool() {
let config = PoolConfig::default();
let pool = Pool::sqlite(":memory:", config).await.unwrap();
assert_eq!(pool.size(), 10);
let conn = pool.get_connection().await.unwrap();
assert!(conn.is_connected());
}
}