torm 0.2.0

A Tokio-based async ORM for Rust with GORM-like API, supporting SQLite, MySQL and PostgreSQL via native wire protocols
Documentation
// Connection Pool Module - Simplified implementation without external dependencies
use crate::db::database::{DatabaseConnection, DbError, ConnectionConfig};
use crate::utils::simple_pool::SimplePool;
use std::sync::Arc;

/// Connection Pool enum for different database types
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 {
    /// Create a new SQLite connection 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)))
    }

    /// Create a new MySQL connection pool
    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)))
    }

    /// Create a new PostgreSQL connection pool
    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)))
    }

    /// Get a connection from the pool
    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))
            }
        }
    }

    /// Return a connection to the pool
    pub async fn return_connection(&self, conn: Arc<dyn DatabaseConnection>) -> Result<(), DbError> {
        match self {
            Pool::SQLite(pool) => {
                // Convert back - this is a simplified approach
                // In real implementation, you'd use downcasting or a different design
                let _ = (pool, conn);
                Ok(())
            }
            Pool::MySQL(pool) => {
                let _ = (pool, conn);
                Ok(())
            }
            Pool::PostgreSQL(pool) => {
                let _ = (pool, conn);
                Ok(())
            }
        }
    }

    /// Get pool status
    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(),
        }
    }

    /// Get pool size
    pub fn size(&self) -> usize {
        match self {
            Pool::SQLite(pool) => pool.size(),
            Pool::MySQL(pool) => pool.size(),
            Pool::PostgreSQL(pool) => pool.size(),
        }
    }

    /// Close all connections in the pool
    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());
    }
}