secra_database/
pool.rs

1//! 连接池管理服务
2//!
3//! 提供数据库连接池的监控和统计功能
4
5use sea_orm::{ConnectionTrait, DatabaseConnection, DatabaseBackend};
6use serde::{Deserialize, Serialize};
7use thiserror::Error;
8use tracing::debug;
9
10/// 连接池错误
11#[derive(Error, Debug)]
12pub enum PoolError {
13    #[error("连接池信息获取失败: {0}")]
14    InfoFailed(String),
15}
16
17/// 连接池统计信息
18#[derive(Debug, Clone, Serialize, Deserialize)]
19pub struct PoolStats {
20    /// 最大连接数
21    pub max_connections: u32,
22    /// 最小连接数
23    pub min_connections: u32,
24    /// 当前活跃连接数(估算)
25    pub active_connections: Option<u32>,
26    /// 当前空闲连接数(估算)
27    pub idle_connections: Option<u32>,
28    /// 等待连接的请求数(估算)
29    pub waiting_requests: Option<u32>,
30}
31
32/// 连接池服务
33pub struct ConnectionPoolService;
34
35impl ConnectionPoolService {
36    /// 获取连接池统计信息
37    ///
38    /// # 注意
39    /// SeaORM 的连接池统计信息获取有限,部分信息可能无法准确获取。
40    /// 对于 PostgreSQL,可以尝试通过系统表查询连接池状态。
41    ///
42    /// # 参数
43    /// * `db` - 数据库连接
44    /// * `max_connections` - 最大连接数(从配置中获取)
45    /// * `min_connections` - 最小连接数(从配置中获取)
46    pub async fn get_pool_stats(
47        db: &DatabaseConnection,
48        max_connections: Option<u32>,
49        min_connections: Option<u32>,
50    ) -> Result<PoolStats, PoolError> {
51        let backend = db.get_database_backend();
52        
53        // 尝试从数据库获取实际的连接池统计信息
54        let (active, idle, waiting) = match backend {
55            DatabaseBackend::Postgres => {
56                // PostgreSQL: 尝试从 pg_stat_activity 获取连接信息
57                match Self::get_postgres_pool_stats(db).await {
58                    Ok(stats) => stats,
59                    Err(e) => {
60                        debug!("无法获取 PostgreSQL 连接池统计信息: {}", e);
61                        (None, None, None)
62                    }
63                }
64            }
65            _ => {
66                // 其他数据库类型暂不支持详细统计
67                (None, None, None)
68            }
69        };
70
71        Ok(PoolStats {
72            max_connections: max_connections.unwrap_or(100),
73            min_connections: min_connections.unwrap_or(5),
74            active_connections: active,
75            idle_connections: idle,
76            waiting_requests: waiting,
77        })
78    }
79
80    /// 获取 PostgreSQL 连接池统计信息
81    ///
82    /// # 注意
83    /// 此方法通过查询 PostgreSQL 系统表获取连接统计信息。
84    /// 返回的是数据库级别的连接数,不是应用连接池的连接数。
85    /// 应用连接池的连接数需要通过连接池配置获取。
86    async fn get_postgres_pool_stats(
87        _db: &DatabaseConnection,
88    ) -> Result<(Option<u32>, Option<u32>, Option<u32>), PoolError> {
89        // 注意:SeaORM 的 DatabaseConnection 不直接暴露查询结果解析 API
90        // 要获取详细的连接池统计信息,需要使用 sqlx 连接池或通过其他方式
91        // 这里返回 None,表示无法获取详细信息
92        // 
93        // 如果需要获取 PostgreSQL 连接统计,可以使用以下 SQL:
94        // SELECT count(*) FROM pg_stat_activity WHERE state = 'active' AND datname = current_database();
95        // SELECT count(*) FROM pg_stat_activity WHERE state = 'idle' AND datname = current_database();
96        
97        debug!("PostgreSQL 连接池统计信息需要通过 sqlx 连接池获取");
98        Ok((None, None, None))
99    }
100
101    /// 测试连接池健康状态
102    pub async fn health_check(db: &DatabaseConnection) -> Result<bool, PoolError> {
103        // 尝试执行一个简单的查询来测试连接池
104        db.execute_unprepared("SELECT 1")
105            .await
106            .map_err(|e| PoolError::InfoFailed(format!("连接池健康检查失败: {}", e)))?;
107
108        Ok(true)
109    }
110}
111
112#[cfg(test)]
113mod tests {
114    use super::*;
115
116    #[test]
117    fn test_pool_stats_serialization() {
118        let stats = PoolStats {
119            max_connections: 100,
120            min_connections: 5,
121            active_connections: Some(10),
122            idle_connections: Some(5),
123            waiting_requests: Some(0),
124        };
125
126        let json = serde_json::to_string(&stats).unwrap();
127        assert!(json.contains("max_connections"));
128    }
129}