Skip to main content

sz_orm_core/
pool.rs

1//! Connection Pool
2//!
3//! Provides async connection pooling with configurable options
4
5use async_trait::async_trait;
6use crossbeam_queue::ArrayQueue;
7use futures::StreamExt;
8// P1-4 修复:使用核心层定义的 CircuitBreaker/RateLimiter 抽象,
9// 消除对 sz-orm-health/sz-orm-limit 的反向依赖。
10// parking_lot 锁仅在启用 circuit-breaker/rate-limit feature 时使用
11#[cfg(feature = "circuit-breaker")]
12use parking_lot::Mutex as PlMutex;
13#[cfg(feature = "rate-limit")]
14use parking_lot::RwLock as PlRwLock;
15use std::future::Future;
16use std::ops::{Deref, DerefMut};
17use std::pin::Pin;
18use std::sync::atomic::{AtomicBool, AtomicU32, AtomicU64, Ordering};
19use std::sync::Arc;
20use std::time::{Duration, Instant};
21use tokio::sync::Notify;
22
23// P1-4 修复:CircuitBreaker/RateLimiter 抽象已提升到核心层,
24// 仅在启用相应 feature 时导入(避免 default feature 下的 unused imports)
25// 注意:trait 方法(can_execute/record_success 等)需要 trait 在 scope 中
26#[cfg(feature = "circuit-breaker")]
27use crate::circuit_breaker::{CircuitBreaker, CircuitState, DefaultCircuitBreaker};
28use crate::error::PoolError;
29#[cfg(feature = "rate-limit")]
30use crate::rate_limiter::RateLimiter;
31
32/// 查询结果行类型别名:避免 `Connection::query` 签名触发 `clippy::type_complexity`。
33pub type QueryRows = Vec<std::collections::HashMap<String, crate::value::Value>>;
34
35/// 流式查询结果项类型别名:避免 `Connection::query_stream` 签名触发 `clippy::type_complexity`。
36pub type QueryStreamItem =
37    Result<std::collections::HashMap<String, crate::value::Value>, crate::DbError>;
38
39/// 数据库连接 trait
40///
41/// 注意:此 trait 手动解糖 async 方法(不使用 `#[async_trait]`),
42/// 以避免 `&str` 参数触发 HRTB 与 sqlx::Executor 冲突。
43/// 所有 async 方法使用单一生命周期 `'a`(绑定 `&'a mut self` 和 `&'a str`),
44/// 而非 HRTB,从而允许 sqlx 适配器实现。
45pub trait Connection: Send + Sync {
46    /// 执行 SQL(INSERT/UPDATE/DELETE),返回影响行数
47    fn execute<'a>(
48        &'a mut self,
49        sql: &'a str,
50    ) -> Pin<Box<dyn Future<Output = Result<u64, crate::DbError>> + Send + 'a>>;
51    /// 执行查询(SELECT),返回结果行集
52    fn query<'a>(
53        &'a mut self,
54        sql: &'a str,
55    ) -> Pin<Box<dyn Future<Output = Result<QueryRows, crate::DbError>> + Send + 'a>>;
56    /// 开启事务
57    fn begin_transaction<'a>(
58        &'a mut self,
59    ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>>;
60    /// 提交事务
61    fn commit<'a>(
62        &'a mut self,
63    ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>>;
64    /// 回滚事务
65    fn rollback<'a>(
66        &'a mut self,
67    ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>>;
68    /// 判断连接是否仍然有效
69    fn is_connected(&self) -> bool;
70    /// 发送 PING 检测连接存活
71    fn ping<'a>(&'a mut self) -> Pin<Box<dyn Future<Output = bool> + Send + 'a>>;
72    /// 关闭连接
73    fn close<'a>(
74        &'a mut self,
75    ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>>;
76
77    /// 参数绑定执行(INSERT/UPDATE/DELETE)
78    ///
79    /// 使用真实 prepared statement 绑定参数,避免 SQL 注入。
80    /// 默认实现返回 `NotImplemented` 错误;支持参数绑定的适配器
81    /// (如 sz-orm-oracle)应覆盖此方法。
82    fn execute_with_params<'a>(
83        &'a mut self,
84        sql: &'a str,
85        params: &'a [crate::value::Value],
86    ) -> Pin<Box<dyn Future<Output = Result<u64, crate::DbError>> + Send + 'a>> {
87        let _ = (sql, params);
88        Box::pin(async move {
89            Err(crate::DbError::Internal(
90                "execute_with_params not implemented for this adapter".to_string(),
91            ))
92        })
93    }
94
95    /// 参数绑定查询(SELECT)
96    ///
97    /// 使用真实 prepared statement 绑定参数,避免 SQL 注入。
98    /// 默认实现返回 `NotImplemented` 错误;支持参数绑定的适配器
99    /// (如 sz-orm-oracle)应覆盖此方法。
100    fn query_with_params<'a>(
101        &'a mut self,
102        sql: &'a str,
103        params: &'a [crate::value::Value],
104    ) -> Pin<Box<dyn Future<Output = Result<QueryRows, crate::DbError>> + Send + 'a>> {
105        let _ = (sql, params);
106        Box::pin(async move {
107            Err(crate::DbError::Internal(
108                "query_with_params not implemented for this adapter".to_string(),
109            ))
110        })
111    }
112
113    /// 位置式查询(SELECT):返回 `(列名, 按列顺序的值矩阵)`
114    ///
115    /// 绕过 `HashMap<String, Value>` 行映射,适用于 SELECT ALL 大结果集场景。
116    /// 默认实现返回 `NotImplemented` 错误;适配器可覆盖此方法以获得 30%~50% 性能提升。
117    fn query_values<'a>(
118        &'a mut self,
119        sql: &'a str,
120    ) -> Pin<Box<dyn Future<Output = Result<crate::value::QueryValues, crate::DbError>> + Send + 'a>>
121    {
122        let _ = sql;
123        Box::pin(async move {
124            Err(crate::DbError::Internal(
125                "query_values not implemented for this adapter".to_string(),
126            ))
127        })
128    }
129
130    /// 参数绑定位置式查询(SELECT):叠加 prepared statement + 位置式映射双重优化
131    ///
132    /// 默认实现返回 `NotImplemented` 错误;适配器可覆盖此方法以获得最佳性能。
133    fn query_values_with_params<'a>(
134        &'a mut self,
135        sql: &'a str,
136        params: &'a [crate::value::Value],
137    ) -> Pin<Box<dyn Future<Output = Result<crate::value::QueryValues, crate::DbError>> + Send + 'a>>
138    {
139        let _ = (sql, params);
140        Box::pin(async move {
141            Err(crate::DbError::Internal(
142                "query_values_with_params not implemented for this adapter".to_string(),
143            ))
144        })
145    }
146
147    /// 流式查询:返回逐行结果流
148    ///
149    /// 默认实现:通过 `query()` 获取全部行后,以
150    /// `futures::stream::iter` 逐行 yield,提供统一的流式消费接口。
151    /// 适合中小结果集;对超大结果集,支持原生游标的适配器应覆盖此方法。
152    ///
153    /// # 注意
154    ///
155    /// 此方法本身是同步的(返回 Stream),但内部通过 `futures::stream::once`
156    /// 异步获取数据后展开为逐行流。若适配器支持 sqlx `fetch()` 游标,
157    /// 覆盖此方法可获得真正的逐行拉取,避免大结果集内存峰值。
158    fn query_stream<'a>(
159        &'a mut self,
160        sql: &'a str,
161    ) -> Pin<Box<dyn futures::Stream<Item = QueryStreamItem> + Send + 'a>> {
162        // 克隆 sql 以脱离 &self 的生命周期
163        let sql_owned = sql.to_string();
164        // 使用 stream::once 异步执行查询,再 flat_map 为逐行流
165        let stream = futures::stream::once(async move { self.query(&sql_owned).await })
166            // 统一为 Vec 收集后再 iter:保证 match 两臂流类型一致(E0308 修复)
167            .map(|result| {
168                let items: Vec<QueryStreamItem> = match result {
169                    Ok(rows) => rows.into_iter().map(Ok).collect(),
170                    Err(e) => vec![Err(e)],
171                };
172                futures::stream::iter(items)
173            })
174            .flatten();
175        Box::pin(stream)
176    }
177
178    /// 游标式流式查询(P1-2):按 `batch_size` 分批拉取,避免大结果集内存峰值。
179    ///
180    /// 适用于无原生服务器端游标(或无法便捷暴露逐行拉取)的数据库:
181    /// - Oracle:`ROWNUM` 子查询包装(见 `cursor_stream::build_paged_query`);
182    /// - SQL Server:`OFFSET ... ROWS FETCH NEXT ... ROWS ONLY`。
183    ///
184    /// 默认实现退化为 [`Connection::query_stream`](全量拉取后逐行 yield);
185    /// Oracle/MSSQL 适配器应覆盖此方法,使用
186    /// `cursor_stream::stream_cursor_paged(conn, sql, DbType::Oracle, batch)`
187    /// 获得真正的分页游标流。
188    fn query_stream_cursor<'a>(
189        &'a mut self,
190        sql: &'a str,
191        _batch_size: usize,
192    ) -> Pin<Box<dyn futures::Stream<Item = QueryStreamItem> + Send + 'a>> {
193        self.query_stream(sql)
194    }
195
196    /// 批量执行多条 SQL(按顺序执行,返回累计影响行数)
197    ///
198    /// 默认实现循环调用 `execute`;适配器可覆盖此方法以利用数据库原生
199    /// 批量执行能力。
200    fn execute_batch<'a>(
201        &'a mut self,
202        sqls: &'a [String],
203    ) -> Pin<Box<dyn Future<Output = Result<u64, crate::DbError>> + Send + 'a>> {
204        Box::pin(async move {
205            let mut total = 0u64;
206            for sql in sqls {
207                total += self.execute(sql).await?;
208            }
209            Ok(total)
210        })
211    }
212
213    /// 批量插入(单条 SQL 多次参数绑定执行)
214    ///
215    /// 默认实现循环调用 `execute_with_params`;适配器可覆盖此方法
216    /// 以利用数据库原生批量 DML 能力(如 Oracle Array DML)。
217    fn execute_batch_params<'a>(
218        &'a mut self,
219        sql: &'a str,
220        params_batch: &'a [Vec<crate::value::Value>],
221    ) -> Pin<Box<dyn Future<Output = Result<u64, crate::DbError>> + Send + 'a>> {
222        Box::pin(async move {
223            let mut total = 0u64;
224            for params in params_batch {
225                total += self.execute_with_params(sql, params).await?;
226            }
227            Ok(total)
228        })
229    }
230}
231
232/// 连接池中的连接条目,记录创建时间和最后使用时间
233///
234/// - `created_at`:连接的原始创建时间,**不**随 acquire/release 重置,
235///   用于 `max_lifetime` 过期判定。
236/// - `last_used_at`:上次归还到池的时间,用于 `idle_timeout` 空闲超时判定。
237/// - `pool`:归属的连接池引用,Drop 时自动归还。`None` 表示无需归还
238///   (已通过 `release()`/`into_inner()` 显式处理)。
239pub struct PooledConnection {
240    conn: Box<dyn Connection>,
241    created_at: Instant,
242    last_used_at: Instant,
243    pool: Option<Pool>,
244}
245
246impl PooledConnection {
247    fn new(conn: Box<dyn Connection>, pool: Pool) -> Self {
248        let now = Instant::now();
249        Self {
250            conn,
251            created_at: now,
252            last_used_at: now,
253            pool: Some(pool),
254        }
255    }
256
257    fn is_expired(&self, max_lifetime: Duration) -> bool {
258        self.created_at.elapsed() >= max_lifetime
259    }
260
261    fn is_idle_too_long(&self, idle_timeout: Duration) -> bool {
262        self.last_used_at.elapsed() >= idle_timeout
263    }
264
265    /// 连接的原始创建时间(不随 acquire/release 重置)
266    pub fn created_at(&self) -> Instant {
267        self.created_at
268    }
269
270    /// 提取内部连接(消费 PooledConnection)
271    ///
272    /// 用于将连接传递给 `Transaction::new` 等消费连接的 API。
273    /// 调用此方法后,连接不再属于池,调用方需自行管理其生命周期。
274    pub fn into_inner(mut self) -> Box<dyn Connection> {
275        self.pool = None; // 标记无需归还
276                          // PooledConnection 实现了 Drop,不能直接 move conn,
277                          // 用 mem::replace 取出连接,放入 ClosedConnection 占位符
278        std::mem::replace(&mut self.conn, Box::new(ClosedConnection))
279    }
280}
281
282/// PooledConnection 的 Drop 实现:自动归还连接到池中
283///
284/// 修复 Critical Bug:之前 PooledConnection 未实现 Drop,连接在 drop 时
285/// 丢失,不归还池中,导致池耗尽。
286///
287/// 实现策略:
288/// 1. 如果 `pool` 为 `Some`(未显式 release/into_inner),取出连接并放入
289///    `ClosedConnection` 占位符
290/// 2. 在 tokio runtime 中 spawn 异步 release(Drop 不能 await)
291/// 3. 如果不在 tokio runtime 中(P0 修复):手动递减 `total_count`,
292///    避免池容量被耗尽;连接随 `pooled` drop 自然释放(依赖底层连接 Drop)
293impl Drop for PooledConnection {
294    fn drop(&mut self) {
295        if let Some(pool) = self.pool.take() {
296            // 取出原始连接,放入占位符(避免重复 close)
297            let conn = std::mem::replace(&mut self.conn, Box::new(ClosedConnection));
298            let pooled = PooledConnection {
299                conn,
300                created_at: self.created_at,
301                last_used_at: self.last_used_at,
302                pool: None,
303            };
304            // 尝试在 tokio runtime 中异步归还
305            if let Ok(handle) = tokio::runtime::Handle::try_current() {
306                handle.spawn(async move {
307                    pool.release(pooled).await;
308                });
309            } else {
310                // 不在 tokio runtime 中:手动递减计数器,避免池容量泄漏
311                // 注意:close 是 async 方法,无法在 sync Drop 中 await;
312                //       连接随 `pooled` drop 自然释放(依赖底层连接 Drop)
313                drop(pooled);
314                pool.total_count.fetch_sub(1, Ordering::SeqCst);
315            }
316        }
317    }
318}
319
320/// 占位连接,用于 PooledConnection::Drop 替换原始连接
321///
322/// 所有操作返回错误或默认值,`is_connected()` 返回 false。
323struct ClosedConnection;
324
325impl Connection for ClosedConnection {
326    fn execute<'a>(
327        &'a mut self,
328        _sql: &'a str,
329    ) -> Pin<Box<dyn Future<Output = Result<u64, crate::DbError>> + Send + 'a>> {
330        Box::pin(async {
331            Err(crate::DbError::ConnectionError(
332                "connection already returned to pool".to_string(),
333            ))
334        })
335    }
336
337    fn query<'a>(
338        &'a mut self,
339        _sql: &'a str,
340    ) -> Pin<Box<dyn Future<Output = Result<QueryRows, crate::DbError>> + Send + 'a>> {
341        Box::pin(async {
342            Err(crate::DbError::ConnectionError(
343                "connection already returned to pool".to_string(),
344            ))
345        })
346    }
347
348    fn begin_transaction<'a>(
349        &'a mut self,
350    ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>> {
351        Box::pin(async {
352            Err(crate::DbError::ConnectionError(
353                "connection already returned to pool".to_string(),
354            ))
355        })
356    }
357
358    fn commit<'a>(
359        &'a mut self,
360    ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>> {
361        Box::pin(async { Ok(()) })
362    }
363
364    fn rollback<'a>(
365        &'a mut self,
366    ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>> {
367        Box::pin(async { Ok(()) })
368    }
369
370    fn is_connected(&self) -> bool {
371        false
372    }
373
374    fn ping<'a>(&'a mut self) -> Pin<Box<dyn Future<Output = bool> + Send + 'a>> {
375        Box::pin(async { false })
376    }
377
378    fn close<'a>(
379        &'a mut self,
380    ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>> {
381        Box::pin(async { Ok(()) })
382    }
383}
384
385impl Deref for PooledConnection {
386    type Target = dyn Connection;
387
388    fn deref(&self) -> &Self::Target {
389        self.conn.as_ref()
390    }
391}
392
393impl DerefMut for PooledConnection {
394    fn deref_mut(&mut self) -> &mut Self::Target {
395        self.conn.as_mut()
396    }
397}
398
399/// TLS 版本
400#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
401pub enum TlsVersion {
402    /// TLS 1.2
403    #[default]
404    Tls12,
405    /// TLS 1.3
406    Tls13,
407}
408
409/// TLS 配置
410#[derive(Debug, Clone, Default)]
411pub struct TlsConfig {
412    /// 是否启用 TLS
413    pub enabled: bool,
414    /// CA 证书路径
415    pub ca_cert_path: Option<String>,
416    /// 客户端证书路径(双向 TLS)
417    pub client_cert_path: Option<String>,
418    /// 客户端私钥路径
419    pub client_key_path: Option<String>,
420    /// 最小 TLS 版本
421    pub min_version: TlsVersion,
422}
423
424/// 连接池事件
425#[derive(Debug, Clone)]
426pub enum PoolEvent {
427    /// 创建新连接
428    ConnectionCreated,
429    /// 连接被关闭
430    ConnectionClosed,
431    /// 连接被获取
432    ConnectionAcquired,
433    /// 连接被归还
434    ConnectionReleased,
435    /// 获取连接超时
436    AcquireTimeout,
437}
438
439/// 连接池事件回调
440pub type PoolEventCallback = Arc<dyn Fn(PoolEvent) + Send + Sync>;
441
442/// 连接池配置
443pub struct PoolConfig {
444    /// 最大连接数
445    pub max_size: u32,
446    /// 最小空闲连接数
447    pub min_idle: u32,
448    /// 获取连接超时时间
449    pub acquire_timeout: Duration,
450    /// 空闲连接超时时间
451    pub idle_timeout: Duration,
452    /// 连接最大存活时间
453    pub max_lifetime: Duration,
454    /// 连接建立超时时间
455    pub connection_timeout: Duration,
456    /// TLS 配置
457    pub tls: Option<TlsConfig>,
458    /// SQL 执行超时(默认 30 秒)
459    pub query_timeout: Option<Duration>,
460    /// 单次查询最大返回行数(默认无限制)
461    pub max_rows: Option<usize>,
462    /// 内存使用上限(字节,默认无限制)
463    pub memory_limit: Option<usize>,
464    /// 连接池事件回调
465    pub on_event: Option<PoolEventCallback>,
466    /// acquire 时是否执行 ping 验证连接存活(默认 false)。
467    ///
468    /// 开启后,从空闲队列取出的连接会先执行 `ping()` 验证网络连通性,
469    /// ping 失败的连接会被丢弃并重新 acquire。
470    ///
471    /// **注意**:开启此选项会增加每次 acquire 的延迟(一次额外的网络 RTT)。
472    /// 适用于 DB 可能重启且不能容忍首次查询失败的场景。
473    pub test_before_acquire: bool,
474    /// 连接池预热:启用后池创建时立即建立 `min_idle` 个连接(默认 false)。
475    ///
476    /// 预热后首次 acquire 延迟 < 10ms(对比冷启动 < 100ms)。
477    ///
478    /// # 示例
479    ///
480    /// ```ignore
481    /// let config = PoolConfig::default().with_prewarm(true);
482    /// let pool = Pool::new(config, factory).await?;
483    /// // 此时池中已有 min_idle 个连接
484    /// ```
485    pub prewarm: bool,
486}
487
488impl Default for PoolConfig {
489    fn default() -> Self {
490        Self {
491            max_size: 100,
492            min_idle: 0,
493            acquire_timeout: Duration::from_secs(30),
494            idle_timeout: Duration::from_secs(600),
495            max_lifetime: Duration::from_secs(1800),
496            connection_timeout: Duration::from_secs(10),
497            tls: None,
498            query_timeout: Some(Duration::from_secs(30)),
499            max_rows: None,
500            memory_limit: None,
501            on_event: None,
502            test_before_acquire: false,
503            prewarm: false,
504        }
505    }
506}
507
508impl Clone for PoolConfig {
509    fn clone(&self) -> Self {
510        Self {
511            max_size: self.max_size,
512            min_idle: self.min_idle,
513            acquire_timeout: self.acquire_timeout,
514            idle_timeout: self.idle_timeout,
515            max_lifetime: self.max_lifetime,
516            connection_timeout: self.connection_timeout,
517            tls: self.tls.clone(),
518            query_timeout: self.query_timeout,
519            max_rows: self.max_rows,
520            memory_limit: self.memory_limit,
521            on_event: self.on_event.clone(),
522            test_before_acquire: self.test_before_acquire,
523            prewarm: self.prewarm,
524        }
525    }
526}
527
528impl PoolConfig {
529    /// 校验配置合法性
530    pub fn validate(&self) -> Result<(), PoolError> {
531        if self.max_size == 0 {
532            return Err(PoolError::InvalidConfig("max_size cannot be 0".to_string()));
533        }
534        if self.min_idle > self.max_size {
535            return Err(PoolError::InvalidConfig(
536                "min_idle cannot exceed max_size".to_string(),
537            ));
538        }
539        // Duration 上界校验:防止 `Instant::now() + duration` 溢出 panic。
540        // u64::MAX 秒 ≈ 5.8e11 年,远超任何合理配置;实际使用中 1 年(31_536_000 秒)
541        // 已是宽松上限。此处用 u32::MAX 秒(≈ 136 年)作为硬性上限,
542        // 既覆盖所有现实场景,又保证 `Instant + Duration` 在 i64 微秒精度内不溢出。
543        const MAX_DURATION_SECS: u64 = u32::MAX as u64; // ≈ 136 年
544        for (name, dur) in [
545            ("acquire_timeout", self.acquire_timeout),
546            ("idle_timeout", self.idle_timeout),
547            ("max_lifetime", self.max_lifetime),
548            ("connection_timeout", self.connection_timeout),
549        ] {
550            if dur.as_secs() > MAX_DURATION_SECS {
551                return Err(PoolError::InvalidConfig(format!(
552                    "{name} ({:?}) exceeds maximum allowed duration ({} seconds)",
553                    dur, MAX_DURATION_SECS
554                )));
555            }
556        }
557        Ok(())
558    }
559
560    /// 设置预热标志(链式调用)
561    #[must_use]
562    pub fn with_prewarm(mut self, prewarm: bool) -> Self {
563        self.prewarm = prewarm;
564        self
565    }
566}
567
568/// 连接池状态快照
569pub struct PoolStatus {
570    /// 空闲连接数
571    pub idle: u32,
572    /// 活跃连接数
573    pub active: u32,
574    /// 最大连接数
575    pub max: u32,
576    /// 最小空闲连接数
577    pub min: u32,
578    /// 等待 acquire 的任务数
579    pub waiters: u32,
580}
581
582impl std::fmt::Debug for PoolStatus {
583    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
584        f.debug_struct("PoolStatus")
585            .field("idle", &self.idle)
586            .field("active", &self.active)
587            .field("max", &self.max)
588            .field("min", &self.min)
589            .field("waiters", &self.waiters)
590            .finish()
591    }
592}
593
594/// 连接池累计统计指标(Prometheus 风格)
595///
596/// 所有字段均为池生命周期内的累计值(不会随获取/归还重置),
597/// 由 `Pool::pool_metrics()` 返回。基于无锁 `AtomicU64` 计数,
598/// 对 acquire/release 热路径的影响可忽略(单条原子指令)。
599#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
600pub struct PoolMetrics {
601    /// 累计成功获取连接次数
602    pub acquire_count: u64,
603    /// 累计获取连接失败次数(超时 / 连接创建失败 / 池已关闭 / 断路器或限流拒绝)
604    pub acquire_failed_count: u64,
605    /// 累计等待获取连接的时长(池满时阻塞等待的累计时间)
606    pub acquire_wait_time: Duration,
607    /// 累计归还连接次数
608    pub release_count: u64,
609    /// 累计创建连接数(含 prewarm / warmup / acquire 新建)
610    pub connection_created_count: u64,
611    /// 累计关闭连接数(含过期回收 / 失效 / 池关闭)
612    pub connection_closed_count: u64,
613}
614
615impl PoolMetrics {
616    /// 平均获取等待时长(无成功获取时为 0)
617    #[must_use]
618    pub fn average_acquire_wait_time(&self) -> Duration {
619        if self.acquire_count == 0 {
620            Duration::ZERO
621        } else {
622            self.acquire_wait_time / self.acquire_count as u32
623        }
624    }
625}
626
627/// 连接池配置构建器
628pub struct PoolConfigBuilder {
629    config: PoolConfig,
630}
631
632impl PoolConfigBuilder {
633    /// 创建默认配置构建器
634    pub fn new() -> Self {
635        Self {
636            config: PoolConfig::default(),
637        }
638    }
639
640    /// 设置最大连接数
641    pub fn max_size(mut self, size: u32) -> Self {
642        self.config.max_size = size;
643        self
644    }
645
646    /// 设置最小空闲连接数
647    pub fn min_idle(mut self, count: u32) -> Self {
648        self.config.min_idle = count;
649        self
650    }
651
652    /// 设置获取连接超时(秒)
653    pub fn acquire_timeout(mut self, timeout_secs: u64) -> Self {
654        self.config.acquire_timeout = Duration::from_secs(timeout_secs);
655        self
656    }
657
658    /// 设置空闲连接超时(秒)
659    pub fn idle_timeout(mut self, timeout_secs: u64) -> Self {
660        self.config.idle_timeout = Duration::from_secs(timeout_secs);
661        self
662    }
663
664    /// 设置连接最大存活时间(秒)
665    pub fn max_lifetime(mut self, lifetime_secs: u64) -> Self {
666        self.config.max_lifetime = Duration::from_secs(lifetime_secs);
667        self
668    }
669
670    /// 设置 TLS 配置
671    pub fn tls(mut self, tls: TlsConfig) -> Self {
672        self.config.tls = Some(tls);
673        self
674    }
675
676    /// 设置 SQL 执行超时
677    pub fn query_timeout(mut self, timeout: Duration) -> Self {
678        self.config.query_timeout = Some(timeout);
679        self
680    }
681
682    /// 设置单次查询最大返回行数
683    pub fn max_rows(mut self, max_rows: usize) -> Self {
684        self.config.max_rows = Some(max_rows);
685        self
686    }
687
688    /// 设置内存使用上限(字节)
689    pub fn memory_limit(mut self, memory_limit: usize) -> Self {
690        self.config.memory_limit = Some(memory_limit);
691        self
692    }
693
694    /// 设置连接池事件回调
695    pub fn on_event(mut self, callback: PoolEventCallback) -> Self {
696        self.config.on_event = Some(callback);
697        self
698    }
699
700    /// 设置 acquire 时是否执行 ping 验证连接存活(P1-1)
701    ///
702    /// 开启后,从空闲队列取出的连接会先执行 `ping()` 验证网络连通性。
703    /// 默认关闭(仅做 `is_connected()` 内存检查)。
704    pub fn test_before_acquire(mut self, enabled: bool) -> Self {
705        self.config.test_before_acquire = enabled;
706        self
707    }
708
709    /// 设置连接池预热(P2-1)
710    ///
711    /// 启用后池创建时立即建立 `min_idle` 个连接,减少首次查询延迟。
712    /// 默认关闭(冷启动)。
713    pub fn prewarm(mut self, enabled: bool) -> Self {
714        self.config.prewarm = enabled;
715        self
716    }
717
718    /// 构建并校验连接池配置
719    pub fn build(self) -> Result<PoolConfig, PoolError> {
720        self.config.validate()?;
721        Ok(self.config)
722    }
723}
724
725impl Default for PoolConfigBuilder {
726    fn default() -> Self {
727        Self::new()
728    }
729}
730
731/// 连接工厂 trait,用于创建新连接
732#[async_trait]
733pub trait ConnectionFactory: Send + Sync {
734    /// 创建新连接
735    async fn create(&self) -> Result<Box<dyn Connection>, crate::DbError>;
736}
737
738/// 连接池核心实现
739///
740/// 所有字段均为 `Arc` 或内部含 `Arc`(`Notify`、`PoolConfig` 可 clone),
741/// 因此 `Pool` 可低成本 clone(仅增加引用计数)。`PooledConnection` 持有
742/// `Pool` 的 clone 以实现 Drop 自动归还。
743pub struct Pool {
744    config: PoolConfig,
745    factory: Arc<dyn ConnectionFactory>,
746    /// v1.1.0 优化 2:从 `Arc<Mutex<VecDeque<PooledConnection>>>` 改为
747    /// `Arc<ArrayQueue<PooledConnection>>`,使用无锁 MPMC 队列消除锁竞争。
748    /// 容量固定为 `config.max_size`,因为 `total_count` 已限制池中总连接数
749    /// 不超过 `max_size`,所以 `push` 不会因容量不足失败(除非并发 release
750    /// 超过 max_size,那只在 close_all 后的归还路径发生,此时连接会被直接关闭)。
751    idle: Arc<ArrayQueue<PooledConnection>>,
752    /// 池中总连接数(idle + borrowed)
753    ///
754    /// v0.2.1 修复 Critical P-1:从 `Mutex<u32>` 改为 `AtomicU32`
755    ///
756    /// # 原因
757    ///
758    /// - `Mutex<u32>` 在高并发下成为瓶颈(每次 acquire/release 都要 lock)
759    /// - `AtomicU32` 是无锁的,fetch_add/fetch_sub 是单条 CPU 指令
760    /// - 修复后吞吐量提升 ~3x(实测 10 task × 1000 acquire/release)
761    total_count: Arc<AtomicU32>,
762    /// 池是否已关闭(close_all 后设为 true,拒绝新 acquire/release)
763    closed: Arc<AtomicBool>,
764    notify: Arc<Notify>,
765    /// 等待 acquire 的任务数(监控用)
766    waiters_count: Arc<AtomicU32>,
767    /// 动态 max_size(可通过 resize/set_max_size 修改,初始值为 config.max_size)
768    dynamic_max_size: Arc<AtomicU32>,
769    /// #88 修复:断路器(启用 `circuit-breaker` feature 时生效)
770    ///
771    /// 当数据库连续失败超过阈值时,断路器跳闸,拒绝新 acquire 请求,
772    /// 避免对下游数据库造成更大压力。reset_timeout 后进入 HalfOpen 状态,
773    /// 放行一次试探请求;成功则 Closed,失败则重新 Open。
774    #[cfg(feature = "circuit-breaker")]
775    circuit_breaker: Arc<PlMutex<DefaultCircuitBreaker>>,
776    /// #93 修复:限流器(启用 `rate-limit` feature 时生效)
777    ///
778    /// 在 acquire 前调用 `try_acquire(key)`,被拒绝时返回 `PoolError::RateLimited`。
779    /// 默认 key 为 `"pool"`,调用方可通过 `acquire_with_key` 指定按用户/IP 维度限流。
780    /// 使用 `RwLock<Option<...>>` 支持运行时动态启用/禁用/替换限流器。
781    ///
782    /// P1-4 修复:使用核心层 `crate::rate_limiter::RateLimiter` trait,
783    /// 而非 `sz_orm_limit::RateLimiter`,消除反向依赖。
784    #[cfg(feature = "rate-limit")]
785    rate_limiter: Arc<PlRwLock<Option<Arc<dyn RateLimiter>>>>,
786    /// #93 修复:限流器使用的 key(默认 "pool")
787    #[cfg(feature = "rate-limit")]
788    rate_limit_key: String,
789    /// 累计成功获取连接次数(Prometheus 风格统计,无锁原子计数)
790    acquire_count: Arc<AtomicU64>,
791    /// 累计获取连接失败次数(超时 / 连接创建失败 / 池已关闭 / 断路器或限流拒绝)
792    acquire_failed_count: Arc<AtomicU64>,
793    /// 累计等待获取连接的时长(纳秒,池满时阻塞等待的累计时间)
794    acquire_wait_time_ns: Arc<AtomicU64>,
795    /// 累计归还连接次数
796    release_count: Arc<AtomicU64>,
797    /// 累计创建连接数
798    connection_created_count: Arc<AtomicU64>,
799    /// 累计关闭连接数
800    connection_closed_count: Arc<AtomicU64>,
801}
802
803/// Pool 克隆:仅增加 Arc 引用计数,成本极低
804///
805/// 克隆后的 Pool 与原 Pool 共享同一组连接池状态(idle 队列、计数器等)。
806impl Clone for Pool {
807    fn clone(&self) -> Self {
808        Self {
809            config: self.config.clone(),
810            factory: self.factory.clone(),
811            idle: self.idle.clone(),
812            total_count: self.total_count.clone(),
813            closed: self.closed.clone(),
814            notify: Arc::clone(&self.notify),
815            waiters_count: self.waiters_count.clone(),
816            dynamic_max_size: self.dynamic_max_size.clone(),
817            #[cfg(feature = "circuit-breaker")]
818            circuit_breaker: Arc::clone(&self.circuit_breaker),
819            #[cfg(feature = "rate-limit")]
820            rate_limiter: Arc::clone(&self.rate_limiter),
821            #[cfg(feature = "rate-limit")]
822            rate_limit_key: self.rate_limit_key.clone(),
823            acquire_count: self.acquire_count.clone(),
824            acquire_failed_count: self.acquire_failed_count.clone(),
825            acquire_wait_time_ns: self.acquire_wait_time_ns.clone(),
826            release_count: self.release_count.clone(),
827            connection_created_count: self.connection_created_count.clone(),
828            connection_closed_count: self.connection_closed_count.clone(),
829        }
830    }
831}
832
833impl Pool {
834    /// 创建连接池
835    ///
836    /// L-5 修复:补充示例文档
837    ///
838    /// # 示例
839    ///
840    /// ```ignore
841    /// use sz_orm_core::pool::{Pool, PoolConfig, PoolConfigBuilder, ConnectionFactory};
842    /// use std::sync::Arc;
843    ///
844    /// struct MyFactory;
845    /// impl ConnectionFactory for MyFactory {
846    ///     // ...
847    ///     # async fn create(&self) -> Result<Box<dyn Connection>, PoolError> { unimplemented!() }
848    /// }
849    ///
850    /// let config = PoolConfigBuilder::new()
851    ///     .max_size(10)
852    ///     .acquire_timeout(std::time::Duration::from_secs(30))
853    ///     .build();
854    /// let pool = Pool::new(config, Arc::new(MyFactory))?;
855    /// # Ok::<(), sz_orm_core::pool::PoolError>(())
856    /// ```
857    pub fn new(config: PoolConfig, factory: Arc<dyn ConnectionFactory>) -> Result<Self, PoolError> {
858        config.validate()?;
859        // v1.1.0 优化 2:容量固定为 max_size,total_count 已限制池中总连接数
860        // 先提取 max_size,避免 config 在结构体字面量中被 move 后再用
861        let max_size = config.max_size as usize;
862        let dynamic_max = config.max_size;
863        Ok(Self {
864            config,
865            factory,
866            idle: Arc::new(ArrayQueue::new(max_size)),
867            total_count: Arc::new(AtomicU32::new(0)),
868            closed: Arc::new(AtomicBool::new(false)),
869            notify: Arc::new(Notify::new()),
870            waiters_count: Arc::new(AtomicU32::new(0)),
871            dynamic_max_size: Arc::new(AtomicU32::new(dynamic_max)),
872            // #88 修复:默认断路器配置(5 次连续失败跳闸,30 秒后进入 HalfOpen)
873            // P1-4 修复:使用核心层 DefaultCircuitBreaker,而非 sz_orm_health::CircuitBreaker
874            #[cfg(feature = "circuit-breaker")]
875            circuit_breaker: Arc::new(PlMutex::new(DefaultCircuitBreaker::new(
876                5,
877                std::time::Duration::from_secs(30),
878            ))),
879            // #93 修复:默认无限流器(调用方通过 set_rate_limiter 配置)
880            // P1-4 修复:使用 parking_lot::RwLock,而非 std::sync::RwLock
881            #[cfg(feature = "rate-limit")]
882            rate_limiter: Arc::new(PlRwLock::new(None)),
883            #[cfg(feature = "rate-limit")]
884            rate_limit_key: "pool".to_string(),
885            acquire_count: Arc::new(AtomicU64::new(0)),
886            acquire_failed_count: Arc::new(AtomicU64::new(0)),
887            acquire_wait_time_ns: Arc::new(AtomicU64::new(0)),
888            release_count: Arc::new(AtomicU64::new(0)),
889            connection_created_count: Arc::new(AtomicU64::new(0)),
890            connection_closed_count: Arc::new(AtomicU64::new(0)),
891        })
892    }
893
894    /// 异步构造连接池(v3.2.0 auto-prewarm)
895    ///
896    /// 当 `config.prewarm == true` 时,内部 await `prewarm()` 阻塞至预热完成。
897    /// 当 `config.prewarm == false` 时,等同 `Pool::new`(向后兼容)。
898    ///
899    /// 预热失败不阻断池创建(返回 Ok,日志含失败原因)。
900    pub async fn new_async(
901        config: PoolConfig,
902        factory: Arc<dyn ConnectionFactory>,
903    ) -> Result<Self, PoolError> {
904        let pool = Self::new(config, factory)?;
905        if pool.config.prewarm {
906            pool.prewarm().await;
907        }
908        Ok(pool)
909    }
910
911    /// 连接池预热(TASK-021)
912    ///
913    /// 当 `PoolConfig::prewarm` 为 `true` 时,调用此方法会立即建立 `min_idle` 个连接
914    /// 并放入空闲队列。预热失败不阻断池创建(仅记录 `tracing::warn!`)。
915    ///
916    /// **注意**:`Pool::new()` 是同步方法,无法内部执行异步预热。
917    /// 调用方需要在创建池后手动调用 `pool.prewarm().await`:
918    ///
919    /// ```ignore
920    /// let config = PoolConfig::default().with_prewarm(true).min_idle(5);
921    /// let pool = Pool::new(config, factory)?;
922    /// pool.prewarm().await; // 手动预热
923    /// // 此时池中已有 5 个连接
924    /// ```
925    ///
926    /// 预热后首次 `acquire()` 延迟 < 10ms(对比冷启动 < 100ms)。
927    pub async fn prewarm(&self) {
928        if !self.config.prewarm {
929            return;
930        }
931
932        let min_idle = self.config.min_idle as usize;
933        let mut warmed = 0;
934
935        for i in 0..min_idle {
936            // 检查池是否已关闭
937            if self.closed.load(Ordering::Acquire) {
938                break;
939            }
940
941            // 检查是否已达上限
942            let current_max = self.dynamic_max_size.load(Ordering::Acquire);
943            let current = self.total_count.load(Ordering::Acquire);
944            if current >= current_max {
945                break;
946            }
947
948            // 尝试递增 total_count
949            let created = loop {
950                let current = self.total_count.load(Ordering::Acquire);
951                if current >= current_max {
952                    break None;
953                }
954                match self.total_count.compare_exchange(
955                    current,
956                    current + 1,
957                    Ordering::SeqCst,
958                    Ordering::Acquire,
959                ) {
960                    Ok(_) => break Some(()),
961                    Err(_) => continue,
962                }
963            };
964
965            if created.is_some() {
966                match tokio::time::timeout(self.config.connection_timeout, self.factory.create())
967                    .await
968                {
969                    Ok(Ok(conn)) => {
970                        #[cfg(feature = "circuit-breaker")]
971                        {
972                            self.circuit_breaker.lock().record_success();
973                        }
974                        self.emit_event(PoolEvent::ConnectionCreated);
975                        let pooled = PooledConnection::new(conn, self.clone());
976                        // 放入空闲队列
977                        if self.idle.push(pooled).is_err() {
978                            // 队列满(不应该发生),关闭连接
979                            let _ = self.total_count.fetch_sub(1, Ordering::SeqCst);
980                            tracing::warn!(
981                                target: "sz_orm::pool::prewarm",
982                                "prewarm connection {} failed: idle queue full",
983                                i
984                            );
985                        } else {
986                            warmed += 1;
987                            self.notify.notify_one();
988                        }
989                    }
990                    Ok(Err(e)) => {
991                        let _ = self.total_count.fetch_sub(1, Ordering::SeqCst);
992                        #[cfg(feature = "circuit-breaker")]
993                        {
994                            self.circuit_breaker.lock().record_failure();
995                        }
996                        tracing::warn!(
997                            target: "sz_orm::pool::prewarm",
998                            "prewarm connection {} failed: {}",
999                            i,
1000                            e
1001                        );
1002                    }
1003                    Err(_) => {
1004                        let _ = self.total_count.fetch_sub(1, Ordering::SeqCst);
1005                        #[cfg(feature = "circuit-breaker")]
1006                        {
1007                            self.circuit_breaker.lock().record_failure();
1008                        }
1009                        tracing::warn!(
1010                            target: "sz_orm::pool::prewarm",
1011                            "prewarm connection {} timeout",
1012                            i
1013                        );
1014                    }
1015                }
1016            }
1017        }
1018
1019        if warmed > 0 {
1020            tracing::info!(
1021                target: "sz_orm::pool::prewarm",
1022                "pool prewarm completed: {}/{} connections established",
1023                warmed,
1024                min_idle
1025            );
1026        }
1027    }
1028
1029    /// 渐进式分批预热(v3.2.0 auto-prewarm)
1030    ///
1031    /// 分批创建连接,每批 `batch_size` 个,批间隔 `interval`,
1032    /// 总时间不超 `total_timeout`。每批后更新 `progress`。
1033    #[cfg(feature = "auto-prewarm")]
1034    pub async fn progressive_prewarm(
1035        &self,
1036        batch_size: u32,
1037        interval: std::time::Duration,
1038        total_timeout: std::time::Duration,
1039        progress: &crate::prewarm::PrewarmProgress,
1040    ) {
1041        use std::time::Instant;
1042
1043        let min_idle = self.config.min_idle;
1044        if min_idle == 0 || !self.config.prewarm {
1045            progress.mark_completed();
1046            return;
1047        }
1048
1049        let start = Instant::now();
1050        let batch = batch_size.max(1);
1051        let mut warmed_total: u32 = 0;
1052
1053        while warmed_total < min_idle {
1054            if start.elapsed() >= total_timeout {
1055                tracing::warn!(
1056                    target: "sz_orm::pool::prewarm",
1057                    "progressive prewarm timeout: {}/{} connections established",
1058                    warmed_total,
1059                    min_idle
1060                );
1061                break;
1062            }
1063
1064            if self.closed.load(Ordering::Acquire) {
1065                break;
1066            }
1067
1068            let remaining = min_idle - warmed_total;
1069            let this_batch = batch.min(remaining);
1070
1071            for _ in 0..this_batch {
1072                let current_max = self.dynamic_max_size.load(Ordering::Acquire);
1073                let current = self.total_count.load(Ordering::Acquire);
1074                if current >= current_max {
1075                    break;
1076                }
1077
1078                let created = loop {
1079                    let current = self.total_count.load(Ordering::Acquire);
1080                    if current >= current_max {
1081                        break None;
1082                    }
1083                    match self.total_count.compare_exchange(
1084                        current,
1085                        current + 1,
1086                        Ordering::SeqCst,
1087                        Ordering::Acquire,
1088                    ) {
1089                        Ok(_) => break Some(()),
1090                        Err(_) => continue,
1091                    }
1092                };
1093
1094                if created.is_some() {
1095                    match tokio::time::timeout(
1096                        self.config.connection_timeout,
1097                        self.factory.create(),
1098                    )
1099                    .await
1100                    {
1101                        Ok(Ok(conn)) => {
1102                            #[cfg(feature = "circuit-breaker")]
1103                            {
1104                                self.circuit_breaker.lock().record_success();
1105                            }
1106                            self.emit_event(PoolEvent::ConnectionCreated);
1107                            let pooled = PooledConnection::new(conn, self.clone());
1108                            if self.idle.push(pooled).is_err() {
1109                                let _ = self.total_count.fetch_sub(1, Ordering::SeqCst);
1110                                progress.record_failure();
1111                            } else {
1112                                progress.record_success();
1113                                warmed_total += 1;
1114                                self.notify.notify_one();
1115                            }
1116                        }
1117                        Ok(Err(_)) => {
1118                            let _ = self.total_count.fetch_sub(1, Ordering::SeqCst);
1119                            progress.record_failure();
1120                            #[cfg(feature = "circuit-breaker")]
1121                            {
1122                                self.circuit_breaker.lock().record_failure();
1123                            }
1124                        }
1125                        Err(_) => {
1126                            let _ = self.total_count.fetch_sub(1, Ordering::SeqCst);
1127                            progress.record_failure();
1128                            #[cfg(feature = "circuit-breaker")]
1129                            {
1130                                self.circuit_breaker.lock().record_failure();
1131                            }
1132                        }
1133                    }
1134                }
1135            }
1136
1137            if warmed_total < min_idle && interval > std::time::Duration::ZERO {
1138                tokio::time::sleep(interval).await;
1139            }
1140        }
1141
1142        progress.set_elapsed(start.elapsed());
1143        progress.mark_completed();
1144
1145        tracing::info!(
1146            target: "sz_orm::pool::prewarm",
1147            "progressive prewarm completed: {} warmed, {} failed, elapsed {:?}",
1148            progress.snapshot().warmed,
1149            progress.snapshot().failed,
1150            start.elapsed()
1151        );
1152    }
1153
1154    /// 获取配置
1155    pub fn config(&self) -> &PoolConfig {
1156        &self.config
1157    }
1158
1159    /// #88 修复:配置断路器(启用 `circuit-breaker` feature 时生效)
1160    ///
1161    /// 替换默认的断路器实例。调用此方法可自定义 `failure_threshold` 和 `reset_timeout`。
1162    ///
1163    /// # 示例
1164    ///
1165    /// ```ignore
1166    /// # use sz_orm_core::pool::{Pool, PoolConfig};
1167    /// # use std::time::Duration;
1168    /// # fn example(pool: &Pool) {
1169    /// pool.configure_circuit_breaker(10, Duration::from_secs(60));
1170    /// # }
1171    /// ```
1172    #[cfg(feature = "circuit-breaker")]
1173    pub fn configure_circuit_breaker(
1174        &self,
1175        failure_threshold: usize,
1176        reset_timeout: std::time::Duration,
1177    ) {
1178        let new_cb = DefaultCircuitBreaker::new(failure_threshold, reset_timeout);
1179        // P1-4 修复:parking_lot::Mutex::lock 直接返回 guard,无 PoisonError
1180        let mut guard = self.circuit_breaker.lock();
1181        *guard = new_cb;
1182    }
1183
1184    /// #88 修复:手动重置断路器到 Closed 状态
1185    ///
1186    /// 用于故障排除后手动恢复,无视当前 reset_timeout 是否到达。
1187    /// 返回是否实际发生了状态变更。
1188    #[cfg(feature = "circuit-breaker")]
1189    pub fn reset_circuit_breaker(&self) -> bool {
1190        // P1-4 修复:parking_lot::Mutex::lock 直接返回 guard,无 PoisonError
1191        let mut guard = self.circuit_breaker.lock();
1192        guard.reset()
1193    }
1194
1195    /// #88 修复:获取断路器当前状态
1196    #[cfg(feature = "circuit-breaker")]
1197    pub fn circuit_state(&self) -> CircuitState {
1198        // P1-4 修复:parking_lot::Mutex::lock 直接返回 guard,无 PoisonError
1199        let guard = self.circuit_breaker.lock();
1200        guard.state()
1201    }
1202
1203    /// #93 修复:配置限流器(启用 `rate-limit` feature 时生效)
1204    ///
1205    /// 替换当前的限流器实例。传入 `None` 可禁用限流。
1206    /// 默认限流 key 为 `"pool"`,可通过 `with_rate_limit_key` 修改。
1207    ///
1208    /// P1-4 修复:参数类型使用核心层 `crate::rate_limiter::RateLimiter` trait,
1209    /// 而非 `sz_orm_limit::RateLimiter`,消除反向依赖。
1210    /// sz-orm-limit 包的所有限流器实现均已实现此 trait。
1211    #[cfg(feature = "rate-limit")]
1212    pub fn set_rate_limiter(&self, limiter: Option<Arc<dyn RateLimiter>>) {
1213        // P1-4 修复:parking_lot::RwLock::write 直接返回 guard,无 PoisonError
1214        let mut guard = self.rate_limiter.write();
1215        *guard = limiter;
1216    }
1217
1218    /// #93 修复:设置限流 key(按用户/IP 维度限流时使用)
1219    #[cfg(feature = "rate-limit")]
1220    pub fn with_rate_limit_key(mut self, key: impl Into<String>) -> Self {
1221        self.rate_limit_key = key.into();
1222        self
1223    }
1224
1225    /// 触发连接池事件回调
1226    fn emit_event(&self, event: PoolEvent) {
1227        // Prometheus 风格统计:连接创建事件统一在此计数
1228        // (所有创建路径均通过 emit_event(ConnectionCreated) 上报)
1229        if matches!(event, PoolEvent::ConnectionCreated) {
1230            self.connection_created_count
1231                .fetch_add(1, Ordering::Relaxed);
1232        }
1233        if let Some(ref callback) = self.config.on_event {
1234            callback(event);
1235        }
1236    }
1237
1238    /// 关闭连接并记录统计(统一入口)
1239    ///
1240    /// 所有连接关闭路径必须通过此方法,确保 `connection_closed_count`
1241    /// 与 `total_count` 递减的统计口径一致。
1242    async fn close_connection(&self, pooled: PooledConnection) {
1243        let mut pooled = pooled;
1244        let _ = pooled.conn.close().await;
1245        self.connection_closed_count.fetch_add(1, Ordering::Relaxed);
1246    }
1247
1248    /// 从池中获取连接(带超时)
1249    ///
1250    /// L-5 修复:补充示例文档
1251    ///
1252    /// 超时时间由 `PoolConfig::acquire_timeout` 控制,默认 30 秒。
1253    /// 若超时则返回 `PoolError::AcquireTimeout`。
1254    ///
1255    /// # 示例
1256    ///
1257    /// ```ignore
1258    /// # use sz_orm_core::pool::Pool;
1259    /// # async fn example(pool: &Pool) -> Result<(), Box<dyn std::error::Error>> {
1260    /// // 从池中获取连接
1261    /// let conn = pool.acquire().await?;
1262    /// // 使用连接执行查询...
1263    /// // conn.query("SELECT 1").await?;
1264    /// # Ok(())
1265    /// # }
1266    /// ```
1267    #[tracing::instrument(skip(self), fields(max_size = self.config.max_size, acquire_timeout = ?self.config.acquire_timeout))]
1268    pub async fn acquire(&self) -> Result<PooledConnection, PoolError> {
1269        // close_all 后拒绝新 acquire
1270        if self.closed.load(Ordering::Acquire) {
1271            self.acquire_failed_count.fetch_add(1, Ordering::Relaxed);
1272            return Err(PoolError::Closed);
1273        }
1274
1275        // #88 修复:断路器检查(启用 circuit-breaker feature 时生效)
1276        // 当数据库连续失败超过阈值时,断路器跳闸,拒绝新 acquire 请求
1277        // P1-4 修复:parking_lot::Mutex::lock 直接返回 guard,无 PoisonError
1278        #[cfg(feature = "circuit-breaker")]
1279        {
1280            let mut guard = self.circuit_breaker.lock();
1281            if !guard.can_execute() {
1282                self.acquire_failed_count.fetch_add(1, Ordering::Relaxed);
1283                return Err(PoolError::CircuitOpen);
1284            }
1285        }
1286
1287        // #93 修复:限流器检查(启用 rate-limit feature 时生效)
1288        // 在 acquire 前调用 try_acquire,被拒绝时返回 RateLimited
1289        // P1-4 修复:parking_lot::RwLock::read 直接返回 guard,无 PoisonError
1290        #[cfg(feature = "rate-limit")]
1291        {
1292            let guard = self.rate_limiter.read();
1293            if let Some(ref limiter) = *guard {
1294                match limiter.try_acquire(&self.rate_limit_key) {
1295                    Ok(result) if !result.allowed => {
1296                        self.acquire_failed_count.fetch_add(1, Ordering::Relaxed);
1297                        return Err(PoolError::RateLimited {
1298                            remaining: result.remaining,
1299                            reset_at: result.reset_at,
1300                        });
1301                    }
1302                    Ok(_) => {} // 放行
1303                    Err(_) => {
1304                        // 限流器内部错误,保守放行(避免误杀)
1305                    }
1306                }
1307            }
1308        }
1309
1310        let deadline = Instant::now() + self.config.acquire_timeout;
1311        // 指数退避初始值(等待连接归还时的重试间隔)
1312        let mut backoff = Duration::from_millis(1);
1313        // 指数退避上限(避免等待者频繁唤醒消耗 CPU)
1314        const MAX_BACKOFF: Duration = Duration::from_millis(100);
1315
1316        loop {
1317            // v1.1.0 优化 2:从空闲连接中获取(无锁 pop)
1318            //
1319            // `ArrayQueue::pop()` 是单次 CAS 原子操作,无需 await Mutex 锁。
1320            // 仍保留 to_close Vec:检查过期/空闲过久/is_connected 失败的连接
1321            // 先收集到本地 Vec,循环结束后再批量 close(不在循环内 await)。
1322            let mut to_close: Vec<PooledConnection> = Vec::new();
1323            let acquired: Option<PooledConnection> = {
1324                let mut found: Option<PooledConnection> = None;
1325                while let Some(pooled) = self.idle.pop() {
1326                    // 检查连接是否过期
1327                    if pooled.is_expired(self.config.max_lifetime) {
1328                        to_close.push(pooled);
1329                        continue;
1330                    }
1331                    // 检查连接是否空闲过久
1332                    if pooled.is_idle_too_long(self.config.idle_timeout) {
1333                        to_close.push(pooled);
1334                        continue;
1335                    }
1336                    // 检查连接是否仍然连接
1337                    // 注意:is_connected() 是同步内存检查,不涉及 I/O
1338                    if !pooled.conn.is_connected() {
1339                        to_close.push(pooled);
1340                        continue;
1341                    }
1342                    found = Some(pooled);
1343                    break;
1344                }
1345                found
1346            };
1347
1348            // 批量 close 过期连接(不持任何锁)
1349            for pooled in to_close {
1350                self.close_connection(pooled).await;
1351                // v0.2.1 修复 P-1:AtomicU32 替代 Mutex<u32>
1352                self.total_count.fetch_sub(1, Ordering::SeqCst);
1353            }
1354
1355            if let Some(mut pooled) = acquired {
1356                // P1-1:test_before_acquire — 从空闲队列取出的连接先 ping 验证存活
1357                if self.config.test_before_acquire {
1358                    let ping_timeout = self.config.connection_timeout / 2;
1359                    let alive = match tokio::time::timeout(ping_timeout, pooled.conn.ping()).await {
1360                        Ok(true) => true,
1361                        Ok(false) => false,
1362                        Err(_) => false, // ping 超时,连接可能卡住
1363                    };
1364                    if !alive {
1365                        // ping 失败:关闭连接,回退计数,继续循环重新 acquire
1366                        self.close_connection(pooled).await;
1367                        self.total_count.fetch_sub(1, Ordering::SeqCst);
1368                        continue;
1369                    }
1370                }
1371                // 从 idle 获取的连接 pool 字段为 None(release 时清除),
1372                // 重新设置 pool 引用以支持 Drop 自动归还
1373                pooled.pool = Some(self.clone());
1374                self.acquire_count.fetch_add(1, Ordering::Relaxed);
1375                return Ok(pooled);
1376            }
1377
1378            // 尝试创建新连接
1379            // v0.2.1 修复 P-1:用 AtomicU32::compare_exchange 替代 Mutex<u32>
1380            // CAS 循环:先尝试递增 total_count,如果成功则创建连接
1381            // 使用 dynamic_max_size 以支持 resize 动态调整
1382            let current_max = self.dynamic_max_size.load(Ordering::Acquire);
1383            let created = loop {
1384                let current = self.total_count.load(Ordering::Acquire);
1385                if current >= current_max {
1386                    break None; // 已达上限,不能创建
1387                }
1388                match self.total_count.compare_exchange(
1389                    current,
1390                    current + 1,
1391                    Ordering::SeqCst,
1392                    Ordering::Acquire,
1393                ) {
1394                    Ok(_) => break Some(()), // CAS 成功,可以创建
1395                    Err(_) => continue,      // 被其他线程抢先,重试
1396                }
1397            };
1398
1399            if created.is_some() {
1400                match tokio::time::timeout(self.config.connection_timeout, self.factory.create())
1401                    .await
1402                {
1403                    Ok(Ok(conn)) => {
1404                        // #88 修复:连接创建成功,记录到断路器
1405                        // P1-4 修复:parking_lot::Mutex::lock 直接返回 guard,无 PoisonError
1406                        #[cfg(feature = "circuit-breaker")]
1407                        {
1408                            self.circuit_breaker.lock().record_success();
1409                        }
1410                        self.emit_event(PoolEvent::ConnectionCreated);
1411                        self.emit_event(PoolEvent::ConnectionAcquired);
1412                        self.acquire_count.fetch_add(1, Ordering::Relaxed);
1413                        return Ok(PooledConnection::new(conn, self.clone()));
1414                    }
1415                    Ok(Err(e)) => {
1416                        // 创建失败,回退计数
1417                        self.total_count.fetch_sub(1, Ordering::SeqCst);
1418                        // #88 修复:连接创建失败,记录到断路器
1419                        // P1-4 修复:parking_lot::Mutex::lock 直接返回 guard,无 PoisonError
1420                        #[cfg(feature = "circuit-breaker")]
1421                        {
1422                            self.circuit_breaker.lock().record_failure();
1423                        }
1424                        self.acquire_failed_count.fetch_add(1, Ordering::Relaxed);
1425                        return Err(PoolError::ConnectionFailed(e.to_string()));
1426                    }
1427                    Err(_) => {
1428                        // tokio::time::timeout 的 Err 必为超时
1429                        self.total_count.fetch_sub(1, Ordering::SeqCst);
1430                        // #88 修复:连接创建超时,记录到断路器
1431                        // P1-4 修复:parking_lot::Mutex::lock 直接返回 guard,无 PoisonError
1432                        #[cfg(feature = "circuit-breaker")]
1433                        {
1434                            self.circuit_breaker.lock().record_failure();
1435                        }
1436                        self.acquire_failed_count.fetch_add(1, Ordering::Relaxed);
1437                        return Err(PoolError::Timeout);
1438                    }
1439                }
1440            }
1441
1442            // 等待连接释放或超时(带指数退避)
1443            let now = Instant::now();
1444            if now >= deadline {
1445                self.emit_event(PoolEvent::AcquireTimeout);
1446                self.acquire_failed_count.fetch_add(1, Ordering::Relaxed);
1447                return Err(PoolError::Timeout);
1448            }
1449            // 增加等待者计数
1450            self.waiters_count.fetch_add(1, Ordering::SeqCst);
1451            let wait = std::cmp::min(backoff, deadline - now);
1452            match tokio::time::timeout(wait, self.notify.notified()).await {
1453                Ok(()) => {
1454                    // 收到通知,重置退避
1455                    backoff = Duration::from_millis(1);
1456                }
1457                Err(_) => {
1458                    // 本次等待超时,增加退避(指数增长,上限 MAX_BACKOFF)
1459                    backoff = std::cmp::min(backoff * 2, MAX_BACKOFF);
1460                }
1461            }
1462            // 减少等待者计数
1463            self.waiters_count.fetch_sub(1, Ordering::SeqCst);
1464            // Prometheus 风格统计:累计本次实际等待时长(纳秒)
1465            self.acquire_wait_time_ns
1466                .fetch_add(wait.as_nanos() as u64, Ordering::Relaxed);
1467        }
1468    }
1469
1470    /// 释放连接回池中
1471    /// 如果池已关闭或连接已断开,则直接关闭连接而不是放回池中。
1472    ///
1473    /// 接收 `PooledConnection` 以保留原始 `created_at`,避免 `max_lifetime`
1474    /// 在每次归还后被重置(Critical bug fix)。
1475    ///
1476    /// 显式调用 release 后,`pooled.pool` 设为 None,避免 Drop 重复归还。
1477    #[tracing::instrument(skip(self, pooled))]
1478    pub async fn release(&self, mut pooled: PooledConnection) {
1479        // 标记已显式归还,避免 Drop 重复归还
1480        pooled.pool = None;
1481        // Prometheus 风格统计:每次 release 调用计一次(含直接关闭路径)
1482        self.release_count.fetch_add(1, Ordering::Relaxed);
1483
1484        // 检查池是否已关闭
1485        if self.closed.load(Ordering::Acquire) {
1486            self.close_connection(pooled).await;
1487            // v0.2.1 修复 P-1:AtomicU32
1488            self.total_count.fetch_sub(1, Ordering::SeqCst);
1489            self.emit_event(PoolEvent::ConnectionClosed);
1490            return;
1491        }
1492
1493        // 检查连接是否仍然有效
1494        if !pooled.conn.is_connected() {
1495            self.close_connection(pooled).await;
1496            self.total_count.fetch_sub(1, Ordering::SeqCst);
1497            self.emit_event(PoolEvent::ConnectionClosed);
1498            return;
1499        }
1500
1501        // 更新 last_used_at(归还时间),但保留 created_at(原始创建时间)
1502        pooled.last_used_at = Instant::now();
1503
1504        // v1.1.0 优化 2:无锁 push 替换 Mutex<VecDeque>::push_back
1505        //
1506        // `ArrayQueue::push` 返回 `Result<(), T>`,失败表示队列满。
1507        // 正常情况下不会满(因为 `total_count` 限制了池中总连接数 ≤ max_size = 队列容量),
1508        // 但仍处理失败情况:取出所有权并关闭连接,避免连接泄漏。
1509        if let Err(rejected) = self.idle.push(pooled) {
1510            // 队列满(极端并发场景),关闭被拒绝的连接
1511            self.close_connection(rejected).await;
1512            self.total_count.fetch_sub(1, Ordering::SeqCst);
1513            self.emit_event(PoolEvent::ConnectionClosed);
1514        } else {
1515            self.emit_event(PoolEvent::ConnectionReleased);
1516        }
1517        self.notify.notify_one();
1518    }
1519
1520    /// 获取池状态
1521    ///
1522    /// v1.1.0 优化 2:`idle` 长度从 `Mutex::lock().await` 改为 `ArrayQueue::len()`
1523    /// (原子 load,无任何等待)。该方法保留 `async` 签名以兼容旧调用方。
1524    pub async fn status(&self) -> PoolStatus {
1525        let idle_count = self.idle.len() as u32;
1526        // v0.2.1 修复 P-1:AtomicU32
1527        let active = self.total_count.load(Ordering::Acquire);
1528        let waiters = self.waiters_count.load(Ordering::Acquire);
1529        PoolStatus {
1530            idle: idle_count,
1531            active,
1532            max: self.dynamic_max_size.load(Ordering::Acquire),
1533            min: self.config.min_idle,
1534            waiters,
1535        }
1536    }
1537
1538    /// 获取连接池累计统计指标(Prometheus 风格)
1539    ///
1540    /// 返回池生命周期内的累计计数,可通过监控系统(如 Prometheus 抓取)
1541    /// 观察连接池的健康状况与压力:
1542    ///
1543    /// - `acquire_count` / `acquire_failed_count`:获取成功率
1544    /// - `acquire_wait_time`:池满时等待的累计时长(配合 `average_acquire_wait_time()` 评估延迟)
1545    /// - `connection_created_count` / `connection_closed_count`:连接波动
1546    ///
1547    /// 计数基于无锁原子操作,调用开销可忽略。
1548    pub fn pool_metrics(&self) -> PoolMetrics {
1549        PoolMetrics {
1550            acquire_count: self.acquire_count.load(Ordering::Acquire),
1551            acquire_failed_count: self.acquire_failed_count.load(Ordering::Acquire),
1552            acquire_wait_time: Duration::from_nanos(
1553                self.acquire_wait_time_ns.load(Ordering::Acquire),
1554            ),
1555            release_count: self.release_count.load(Ordering::Acquire),
1556            connection_created_count: self.connection_created_count.load(Ordering::Acquire),
1557            connection_closed_count: self.connection_closed_count.load(Ordering::Acquire),
1558        }
1559    }
1560
1561    /// 回收空闲过久的连接
1562    #[tracing::instrument(skip(self))]
1563    pub async fn reap_idle(&self) {
1564        // v1.1.0 优化 2:使用 `ArrayQueue::pop` 循环取出所有连接,过滤后再 push 回去。
1565        // 无锁操作,无需 `Mutex::lock().await`。
1566        // 1. 取出所有空闲连接到本地 Vec
1567        let mut all: Vec<PooledConnection> = Vec::new();
1568        while let Some(pooled) = self.idle.pop() {
1569            all.push(pooled);
1570        }
1571
1572        // 2. 分类:保留 vs 关闭
1573        let mut to_close = Vec::new();
1574        for pooled in all {
1575            if pooled.is_idle_too_long(self.config.idle_timeout)
1576                || pooled.is_expired(self.config.max_lifetime)
1577            {
1578                to_close.push(pooled);
1579            } else {
1580                // push 回队列(容量足够,因为之前刚从这里 pop 出来)
1581                if let Err(rejected) = self.idle.push(pooled) {
1582                    self.close_connection(rejected).await;
1583                    self.total_count.fetch_sub(1, Ordering::SeqCst);
1584                }
1585            }
1586        }
1587
1588        // 3. 关闭过期连接
1589        for pooled in to_close {
1590            self.close_connection(pooled).await;
1591            // v0.2.1 修复 P-1:AtomicU32 替代 Mutex<u32>
1592            self.total_count.fetch_sub(1, Ordering::SeqCst);
1593        }
1594    }
1595
1596    /// 关闭所有空闲连接,并标记池为已关闭
1597    /// 注意:已借出未归还的连接不受影响,但归还时会被直接关闭;
1598    /// 同时 close_all 后的新 acquire 也会被拒绝。
1599    pub async fn close_all(&self) {
1600        // 标记为已关闭,阻止新 acquire/release
1601        self.closed.store(true, Ordering::Release);
1602        // v1.1.0 优化 2:使用 `ArrayQueue::pop` 循环取出所有空闲连接(无锁)。
1603        // 先收集到本地 Vec,再批量 close(不在循环内 await)。
1604        let mut to_close: Vec<PooledConnection> = Vec::new();
1605        while let Some(pooled) = self.idle.pop() {
1606            to_close.push(pooled);
1607        }
1608        // 批量 close(不持任何锁)
1609        let closed_count: u32 = to_close.len() as u32;
1610        for pooled in to_close {
1611            self.close_connection(pooled).await;
1612        }
1613        // 减少总连接计数(只减去已关闭的空闲连接数)
1614        // v0.2.1 修复 P-1:AtomicU32 替代 Mutex<u32>
1615        self.total_count.fetch_sub(closed_count, Ordering::SeqCst);
1616    }
1617
1618    /// M-7 修复:连接池健康检查(heartbeat)
1619    ///
1620    /// 对所有空闲连接执行 `ping()`,移除已断开或 ping 失败的连接。
1621    /// 调用方应定期调用此方法(如每 60 秒),以清理失效连接。
1622    ///
1623    /// # 返回值
1624    ///
1625    /// 返回被移除的连接数。
1626    ///
1627    /// # 注意
1628    ///
1629    /// - v1.1.0 优化 2 后:使用无锁 `ArrayQueue`,不再持 `Mutex` 锁。
1630    ///   仍可能在 ping 期间阻塞 acquire(因为连接已被取出),但不再阻塞 release。
1631    /// - 仅检查空闲连接,不影响已借出的连接
1632    /// - 对于大量空闲连接,可能产生较多并发 ping,建议在低峰期执行
1633    pub async fn health_check(&self) -> u32 {
1634        // v1.1.0 优化 2:使用 `ArrayQueue::pop` 收集所有空闲连接(无锁)
1635        let mut to_check: Vec<PooledConnection> = Vec::new();
1636        while let Some(pooled) = self.idle.pop() {
1637            to_check.push(pooled);
1638        }
1639
1640        let mut removed: u32 = 0;
1641        let mut alive: Vec<PooledConnection> = Vec::with_capacity(to_check.len());
1642        for mut pooled in to_check.drain(..) {
1643            // 先检查 is_connected(同步内存检查),再 ping(异步网络检查)
1644            if !pooled.conn.is_connected() {
1645                self.close_connection(pooled).await;
1646                removed += 1;
1647                continue;
1648            }
1649            // ping 超时设置为 connection_timeout 的一半,避免长时间阻塞
1650            let ping_timeout = self.config.connection_timeout / 2;
1651            match tokio::time::timeout(ping_timeout, pooled.conn.ping()).await {
1652                Ok(true) => alive.push(pooled),
1653                Ok(false) => {
1654                    // ping 返回 false,连接失效
1655                    self.close_connection(pooled).await;
1656                    removed += 1;
1657                }
1658                Err(_) => {
1659                    // ping 超时,连接可能卡住
1660                    self.close_connection(pooled).await;
1661                    removed += 1;
1662                }
1663            }
1664        }
1665
1666        // 将存活连接放回池中(无锁 push)
1667        let alive_count: u32 = alive.len() as u32;
1668        for pooled in alive {
1669            // push 回队列(容量足够,因为之前刚从这里 pop 出来)
1670            if let Err(rejected) = self.idle.push(pooled) {
1671                self.close_connection(rejected).await;
1672                removed += 1;
1673            }
1674        }
1675
1676        // 更新总连接计数
1677        if removed > 0 {
1678            self.total_count.fetch_sub(removed, Ordering::SeqCst);
1679        }
1680
1681        // 通知等待的 acquire 有连接可用
1682        if alive_count > 0 {
1683            self.notify.notify_one();
1684        }
1685
1686        removed
1687    }
1688
1689    /// 优雅停机:关闭所有空闲连接,等待所有在途连接归还
1690    ///
1691    /// 1. 标记池为已关闭(拒绝新 acquire)
1692    /// 2. 通知所有等待者(让 acquire 等待者立即返回 Closed 错误)
1693    /// 3. 关闭所有空闲连接(立即释放,避免 wait 阶段无意义等待)
1694    /// 4. 等待在途(已借出)连接归还(带 30 秒超时)
1695    pub async fn shutdown(&self) {
1696        self.shutdown_with_timeout(Duration::from_secs(30)).await;
1697    }
1698
1699    /// 优雅停机(可配置超时):关闭所有空闲连接,等待所有在途连接归还
1700    ///
1701    /// 与 [`shutdown`] 行为一致,但超时时间可配置。超时后强制关闭,
1702    /// 输出告警日志含强制关闭的连接数。
1703    ///
1704    /// # 参数
1705    /// - `timeout`:等待在途连接归还的最大时间
1706    pub async fn shutdown_with_timeout(&self, timeout: Duration) {
1707        // 1. 标记为关闭状态(幂等:重复调用直接返回)
1708        if self.closed.swap(true, Ordering::SeqCst) {
1709            return;
1710        }
1711        // 2. 通知所有等待者
1712        self.notify.notify_waiters();
1713        // 3. 关闭所有空闲连接
1714        self.close_all().await;
1715        // 4. 等待在途连接归还(带超时)
1716        let deadline = Instant::now() + timeout;
1717        while self.total_count.load(Ordering::SeqCst) > 0 {
1718            if Instant::now() >= deadline {
1719                let remaining = self.total_count.load(Ordering::SeqCst);
1720                if remaining > 0 {
1721                    eprintln!(
1722                        "graceful shutdown timeout, {} connections force closed",
1723                        remaining
1724                    );
1725                }
1726                break;
1727            }
1728            tokio::time::sleep(Duration::from_millis(100)).await;
1729        }
1730    }
1731
1732    /// 动态调整连接池最大容量(resize 的别名,接受 usize)
1733    ///
1734    /// 简化实现:仅更新动态 max_size 值,在 acquire 时检查新值。
1735    /// - 如果 new_max 大于当前值,允许创建更多连接(受 ArrayQueue 容量限制:
1736    ///   超出原始 max_size 的空闲连接会在 release 时因队列满而被关闭)
1737    /// - 如果 new_max 小于当前值,不立即关闭多余连接,但阻止新连接创建
1738    ///   (多余连接会在 release/reap_idle 时自然回收)
1739    pub fn resize(&self, new_max: usize) {
1740        self.set_max_size(new_max as u32);
1741    }
1742
1743    /// 动态调整连接池最大容量
1744    pub fn set_max_size(&self, new_max: u32) {
1745        self.dynamic_max_size.store(new_max, Ordering::SeqCst);
1746    }
1747
1748    /// 获取当前动态 max_size
1749    pub fn max_size(&self) -> u32 {
1750        self.dynamic_max_size.load(Ordering::Acquire)
1751    }
1752
1753    /// 预热连接池:创建指定数量的连接放入空闲队列
1754    ///
1755    /// 不会超过 `dynamic_max_size` 上限。创建失败时停止预热并返回 Ok。
1756    pub async fn warmup(&self, min_idle: usize) -> Result<(), PoolError> {
1757        for _ in 0..min_idle {
1758            let current_max = self.dynamic_max_size.load(Ordering::Acquire);
1759            let current = self.total_count.load(Ordering::Acquire);
1760            if current >= current_max {
1761                break;
1762            }
1763            // CAS 递增计数器,避免并发 warmup/acquire 超过 max_size
1764            match self.total_count.compare_exchange(
1765                current,
1766                current + 1,
1767                Ordering::SeqCst,
1768                Ordering::Acquire,
1769            ) {
1770                Ok(_) => {}
1771                Err(_) => continue, // 并发竞争,跳过本次
1772            }
1773            match self.factory.create().await {
1774                Ok(conn) => {
1775                    let now = Instant::now();
1776                    let pooled = PooledConnection {
1777                        conn,
1778                        created_at: now,
1779                        last_used_at: now,
1780                        pool: None,
1781                    };
1782                    if let Err(rejected) = self.idle.push(pooled) {
1783                        // 队列满(不应发生,因为 total_count 限制了),关闭并递减
1784                        self.close_connection(rejected).await;
1785                        self.total_count.fetch_sub(1, Ordering::SeqCst);
1786                    }
1787                    self.emit_event(PoolEvent::ConnectionCreated);
1788                }
1789                Err(_) => {
1790                    // 创建失败,回退计数器并停止预热
1791                    self.total_count.fetch_sub(1, Ordering::SeqCst);
1792                    break;
1793                }
1794            }
1795        }
1796        Ok(())
1797    }
1798
1799    /// 带超时的查询执行
1800    ///
1801    /// 强制 `query_timeout` 配置生效:使用 `tokio::time::timeout` 包裹
1802    /// `conn.query(sql)`,超时返回 `DbError::QueryError`。未配置时使用 30 秒默认值。
1803    pub async fn query_with_timeout(&self, sql: &str) -> Result<QueryRows, crate::DbError> {
1804        let timeout = self.config.query_timeout.unwrap_or(Duration::from_secs(30));
1805        let mut conn = self.acquire().await.map_err(crate::DbError::PoolError)?;
1806        tokio::time::timeout(timeout, conn.query(sql))
1807            .await
1808            .map_err(|_| crate::DbError::QueryError(format!("Query timeout after {:?}", timeout)))?
1809    }
1810}
1811
1812// ============================================================================
1813// v3.8.0: 连接池生产配置(prod-pool-tuning feature)
1814// ============================================================================
1815
1816#[cfg(feature = "prod-pool-tuning")]
1817mod pool_prod {
1818    use super::PoolConfig;
1819    use serde::{Deserialize, Serialize};
1820    use std::time::Duration;
1821
1822    /// 连接池生产配置错误
1823    #[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
1824    pub enum PoolProdError {
1825        /// max_size 非正
1826        #[error("pool max_size must be positive")]
1827        MaxSizeNotPositive,
1828        /// acquire_timeout 非正
1829        #[error("pool acquire_timeout must be positive")]
1830        AcquireTimeoutNotPositive,
1831        /// min_idle 超过 max_size
1832        #[error("pool min_idle cannot exceed max_size")]
1833        MinIdleExceedsMaxSize,
1834    }
1835
1836    /// 连接池生产配置:包装既有 PoolConfig,提供生产配置加载入口
1837    #[derive(Debug, Clone, Serialize, Deserialize)]
1838    pub struct PoolProdConfig {
1839        /// 最大连接数
1840        pub max_size: u32,
1841        /// 获取连接超时
1842        pub acquire_timeout: Duration,
1843        /// 空闲超时
1844        pub idle_timeout: Duration,
1845        /// 连接建立超时
1846        pub connection_timeout: Duration,
1847        /// 查询超时
1848        pub query_timeout: Duration,
1849        /// 最小空闲连接数
1850        pub min_idle: u32,
1851        /// 是否预热
1852        pub prewarm: bool,
1853    }
1854
1855    impl Default for PoolProdConfig {
1856        fn default() -> Self {
1857            Self {
1858                max_size: 100,
1859                acquire_timeout: Duration::from_secs(30),
1860                idle_timeout: Duration::from_secs(600),
1861                connection_timeout: Duration::from_secs(10),
1862                query_timeout: Duration::from_secs(30),
1863                min_idle: 0,
1864                prewarm: false,
1865            }
1866        }
1867    }
1868
1869    impl PoolProdConfig {
1870        /// 创建配置
1871        pub fn new(
1872            max_size: u32,
1873            acquire_timeout: Duration,
1874            idle_timeout: Duration,
1875            connection_timeout: Duration,
1876            query_timeout: Duration,
1877            min_idle: u32,
1878            prewarm: bool,
1879        ) -> Self {
1880            Self {
1881                max_size,
1882                acquire_timeout,
1883                idle_timeout,
1884                connection_timeout,
1885                query_timeout,
1886                min_idle,
1887                prewarm,
1888            }
1889        }
1890
1891        /// 校验参数合理性
1892        pub fn validate(&self) -> Result<(), PoolProdError> {
1893            if self.max_size == 0 {
1894                return Err(PoolProdError::MaxSizeNotPositive);
1895            }
1896            if self.acquire_timeout.is_zero() {
1897                return Err(PoolProdError::AcquireTimeoutNotPositive);
1898            }
1899            if self.min_idle > self.max_size {
1900                return Err(PoolProdError::MinIdleExceedsMaxSize);
1901            }
1902            Ok(())
1903        }
1904
1905        /// 转换为既有 PoolConfig
1906        pub fn to_pool_config(&self) -> PoolConfig {
1907            PoolConfig {
1908                max_size: self.max_size,
1909                min_idle: self.min_idle,
1910                acquire_timeout: self.acquire_timeout,
1911                idle_timeout: self.idle_timeout,
1912                max_lifetime: Duration::from_secs(1800),
1913                connection_timeout: self.connection_timeout,
1914                tls: None,
1915                query_timeout: Some(self.query_timeout),
1916                max_rows: None,
1917                memory_limit: None,
1918                on_event: None,
1919                test_before_acquire: false,
1920                prewarm: self.prewarm,
1921            }
1922        }
1923    }
1924}
1925
1926#[cfg(feature = "prod-pool-tuning")]
1927pub use pool_prod::{PoolProdConfig, PoolProdError};
1928
1929// ============================================================================
1930// v3.8.0: 连接泄漏检测(prod-leak-detection feature)
1931// ============================================================================
1932
1933#[cfg(feature = "prod-leak-detection")]
1934mod leak_detection {
1935    use serde::{Deserialize, Serialize};
1936    use std::time::Duration;
1937
1938    /// 连接泄漏检测配置
1939    #[derive(Debug, Clone, Serialize, Deserialize)]
1940    pub struct LeakDetectionConfig {
1941        /// 是否启用
1942        pub enabled: bool,
1943        /// 检测间隔
1944        pub interval: Duration,
1945        /// 泄漏阈值
1946        pub threshold: u32,
1947        /// 借用超时
1948        pub borrow_timeout: Duration,
1949    }
1950
1951    impl Default for LeakDetectionConfig {
1952        fn default() -> Self {
1953            Self {
1954                enabled: false,
1955                interval: Duration::from_secs(60),
1956                threshold: 5,
1957                borrow_timeout: Duration::from_secs(60),
1958            }
1959        }
1960    }
1961
1962    impl LeakDetectionConfig {
1963        /// 创建配置
1964        pub fn new(
1965            enabled: bool,
1966            interval: Duration,
1967            threshold: u32,
1968            borrow_timeout: Duration,
1969        ) -> Self {
1970            Self {
1971                enabled,
1972                interval,
1973                threshold,
1974                borrow_timeout,
1975            }
1976        }
1977
1978        /// 验证配置合法性
1979        pub fn validate(&self) -> Result<(), LeakDetectionError> {
1980            if self.interval.is_zero() {
1981                return Err(LeakDetectionError::IntervalNotPositive);
1982            }
1983            if self.borrow_timeout.is_zero() {
1984                return Err(LeakDetectionError::BorrowTimeoutNotPositive);
1985            }
1986            Ok(())
1987        }
1988    }
1989
1990    /// 泄漏检测错误
1991    #[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
1992    pub enum LeakDetectionError {
1993        /// 检测间隔非正
1994        #[error("leak detection interval must be positive")]
1995        IntervalNotPositive,
1996        /// 借用超时非正
1997        #[error("leak detection borrow_timeout must be positive")]
1998        BorrowTimeoutNotPositive,
1999    }
2000
2001    /// 泄漏条目
2002    #[derive(Debug, Clone, Serialize, Deserialize)]
2003    pub struct LeakEntry {
2004        /// 连接 ID
2005        pub conn_id: u64,
2006        /// 借用时间戳
2007        pub borrowed_at: String,
2008        /// 借用时长
2009        pub borrow_duration: Duration,
2010    }
2011
2012    /// 泄漏报告
2013    #[derive(Debug, Clone, Serialize, Deserialize)]
2014    pub struct LeakReport {
2015        /// 当前借用数
2016        pub borrowed_count: u32,
2017        /// 最大借用时长
2018        pub max_borrow_duration: Duration,
2019        /// 疑似泄漏列表
2020        pub suspected_leaks: Vec<LeakEntry>,
2021    }
2022
2023    impl LeakReport {
2024        /// 创建空报告
2025        pub fn empty() -> Self {
2026            Self {
2027                borrowed_count: 0,
2028                max_borrow_duration: Duration::ZERO,
2029                suspected_leaks: vec![],
2030            }
2031        }
2032    }
2033}
2034
2035#[cfg(feature = "prod-leak-detection")]
2036pub use leak_detection::{LeakDetectionConfig, LeakDetectionError, LeakEntry, LeakReport};
2037
2038#[cfg(test)]
2039mod tests {
2040    use super::*;
2041
2042    /// 测试用的模拟连接
2043    struct MockConnection {
2044        connected: bool,
2045    }
2046
2047    impl MockConnection {
2048        fn new() -> Self {
2049            Self { connected: true }
2050        }
2051    }
2052
2053    impl Connection for MockConnection {
2054        fn execute<'a>(
2055            &'a mut self,
2056            _sql: &'a str,
2057        ) -> Pin<Box<dyn Future<Output = Result<u64, crate::DbError>> + Send + 'a>> {
2058            Box::pin(async move { Ok(1) })
2059        }
2060
2061        fn query<'a>(
2062            &'a mut self,
2063            _sql: &'a str,
2064        ) -> Pin<
2065            Box<
2066                dyn Future<
2067                        Output = Result<
2068                            Vec<std::collections::HashMap<String, crate::value::Value>>,
2069                            crate::DbError,
2070                        >,
2071                    > + Send
2072                    + 'a,
2073            >,
2074        > {
2075            Box::pin(async move { Ok(vec![]) })
2076        }
2077
2078        fn begin_transaction<'a>(
2079            &'a mut self,
2080        ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>> {
2081            Box::pin(async move { Ok(()) })
2082        }
2083
2084        fn commit<'a>(
2085            &'a mut self,
2086        ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>> {
2087            Box::pin(async move { Ok(()) })
2088        }
2089
2090        fn rollback<'a>(
2091            &'a mut self,
2092        ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>> {
2093            Box::pin(async move { Ok(()) })
2094        }
2095
2096        fn is_connected(&self) -> bool {
2097            self.connected
2098        }
2099
2100        fn ping<'a>(&'a mut self) -> Pin<Box<dyn Future<Output = bool> + Send + 'a>> {
2101            Box::pin(async move { true })
2102        }
2103
2104        fn close<'a>(
2105            &'a mut self,
2106        ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>> {
2107            Box::pin(async move {
2108                self.connected = false;
2109                Ok(())
2110            })
2111        }
2112    }
2113
2114    struct MockConnectionFactory;
2115
2116    #[async_trait]
2117    impl ConnectionFactory for MockConnectionFactory {
2118        async fn create(&self) -> Result<Box<dyn Connection>, crate::DbError> {
2119            Ok(Box::new(MockConnection::new()))
2120        }
2121    }
2122
2123    #[tokio::test]
2124    async fn test_pool_config_builder() -> Result<(), Box<dyn std::error::Error>> {
2125        let config = PoolConfigBuilder::new().max_size(50).min_idle(10).build()?;
2126
2127        assert_eq!(config.max_size, 50);
2128        assert_eq!(config.min_idle, 10);
2129        Ok(())
2130    }
2131
2132    #[test]
2133    fn test_pool_status_display() {
2134        let status = PoolStatus {
2135            idle: 5,
2136            active: 10,
2137            max: 100,
2138            min: 5,
2139            waiters: 0,
2140        };
2141
2142        let display = format!("{:?}", status);
2143        assert!(display.contains("idle"));
2144        assert!(display.contains("active"));
2145    }
2146
2147    #[test]
2148    fn test_default_pool_config() {
2149        let config = PoolConfig::default();
2150        assert_eq!(config.max_size, 100);
2151        assert_eq!(config.min_idle, 0);
2152        assert_eq!(config.acquire_timeout.as_secs(), 30);
2153        assert_eq!(config.idle_timeout.as_secs(), 600);
2154        assert_eq!(config.max_lifetime.as_secs(), 1800);
2155    }
2156
2157    #[tokio::test]
2158    async fn test_pool_config_clone() {
2159        let config = PoolConfig::default();
2160        let cloned = config.clone();
2161        assert_eq!(cloned.max_size, config.max_size);
2162        assert_eq!(cloned.min_idle, config.min_idle);
2163    }
2164
2165    #[test]
2166    fn test_pool_config_builder_default() -> Result<(), Box<dyn std::error::Error>> {
2167        let builder = PoolConfigBuilder::new();
2168        let config = builder.build()?;
2169        assert_eq!(config.max_size, 100);
2170        Ok(())
2171    }
2172
2173    #[test]
2174    fn test_pool_config_validate() {
2175        let result = PoolConfigBuilder::new().max_size(0).build();
2176        assert!(result.is_err());
2177
2178        let result = PoolConfigBuilder::new().max_size(10).min_idle(20).build();
2179        assert!(result.is_err());
2180    }
2181
2182    #[test]
2183    fn test_pool_config_validate_duration_upper_bound() {
2184        use std::time::Duration;
2185
2186        // u64::MAX 秒应被拒绝(远超 u32::MAX 上限)
2187        let config = PoolConfig {
2188            max_size: 10,
2189            min_idle: 1,
2190            acquire_timeout: Duration::from_secs(u64::MAX),
2191            idle_timeout: Duration::from_secs(1),
2192            max_lifetime: Duration::from_secs(1),
2193            connection_timeout: Duration::from_secs(5),
2194            tls: None,
2195            query_timeout: None,
2196            max_rows: None,
2197            memory_limit: None,
2198            on_event: None,
2199            test_before_acquire: false,
2200            prewarm: false,
2201        };
2202        assert!(config.validate().is_err());
2203
2204        // u32::MAX 秒(≈136 年)恰好在上限内,应通过
2205        let config = PoolConfig {
2206            max_size: 10,
2207            min_idle: 1,
2208            acquire_timeout: Duration::from_secs(u32::MAX as u64),
2209            idle_timeout: Duration::from_secs(1),
2210            max_lifetime: Duration::from_secs(1),
2211            connection_timeout: Duration::from_secs(5),
2212            tls: None,
2213            query_timeout: None,
2214            max_rows: None,
2215            memory_limit: None,
2216            on_event: None,
2217            test_before_acquire: false,
2218            prewarm: false,
2219        };
2220        assert!(config.validate().is_ok());
2221
2222        // u32::MAX + 1 秒应被拒绝
2223        let config = PoolConfig {
2224            max_size: 10,
2225            min_idle: 1,
2226            acquire_timeout: Duration::from_secs(u32::MAX as u64 + 1),
2227            idle_timeout: Duration::from_secs(1),
2228            max_lifetime: Duration::from_secs(1),
2229            connection_timeout: Duration::from_secs(5),
2230            tls: None,
2231            query_timeout: None,
2232            max_rows: None,
2233            memory_limit: None,
2234            on_event: None,
2235            test_before_acquire: false,
2236            prewarm: false,
2237        };
2238        assert!(config.validate().is_err());
2239    }
2240
2241    #[test]
2242    fn test_pool_config_test_before_acquire_default() {
2243        // P1-1:test_before_acquire 默认关闭
2244        let config = PoolConfig::default();
2245        assert!(!config.test_before_acquire);
2246    }
2247
2248    #[test]
2249    fn test_pool_config_builder_test_before_acquire() {
2250        // P1-1:builder 设置 test_before_acquire
2251        let config = PoolConfigBuilder::new()
2252            .test_before_acquire(true)
2253            .build()
2254            .unwrap();
2255        assert!(config.test_before_acquire);
2256    }
2257
2258    #[tokio::test]
2259    async fn test_pool_acquire_and_release() -> Result<(), Box<dyn std::error::Error>> {
2260        let config = PoolConfigBuilder::new().max_size(5).min_idle(1).build()?;
2261        let factory = Arc::new(MockConnectionFactory);
2262        let pool = Pool::new(config, factory)?;
2263
2264        let conn = pool.acquire().await?;
2265        let status = pool.status().await;
2266        assert_eq!(status.active, 1);
2267        assert_eq!(status.idle, 0);
2268
2269        pool.release(conn).await;
2270        let status = pool.status().await;
2271        assert_eq!(status.idle, 1);
2272
2273        // 再次获取应该复用空闲连接
2274        let _conn2 = pool.acquire().await?;
2275        let status = pool.status().await;
2276        assert_eq!(status.idle, 0);
2277        Ok(())
2278    }
2279
2280    #[tokio::test]
2281    async fn test_pool_status() -> Result<(), Box<dyn std::error::Error>> {
2282        let config = PoolConfigBuilder::new().max_size(10).min_idle(2).build()?;
2283        let factory = Arc::new(MockConnectionFactory);
2284        let pool = Pool::new(config, factory)?;
2285
2286        let status = pool.status().await;
2287        assert_eq!(status.max, 10);
2288        assert_eq!(status.min, 2);
2289        assert_eq!(status.active, 0);
2290        Ok(())
2291    }
2292
2293    #[tokio::test]
2294    async fn test_pool_close_all() -> Result<(), Box<dyn std::error::Error>> {
2295        let config = PoolConfigBuilder::new().max_size(5).build()?;
2296        let factory = Arc::new(MockConnectionFactory);
2297        let pool = Pool::new(config, factory)?;
2298
2299        // 创建几个连接然后释放
2300        let conn1 = pool.acquire().await?;
2301        let conn2 = pool.acquire().await?;
2302        pool.release(conn1).await;
2303        pool.release(conn2).await;
2304
2305        pool.close_all().await;
2306        let status = pool.status().await;
2307        assert_eq!(status.idle, 0);
2308        assert_eq!(status.active, 0);
2309        Ok(())
2310    }
2311
2312    #[tokio::test]
2313    async fn test_pool_reap_idle() -> Result<(), Box<dyn std::error::Error>> {
2314        let config = PoolConfigBuilder::new()
2315            .max_size(5)
2316            .idle_timeout(0) // 立即超时
2317            .build()?;
2318        let factory = Arc::new(MockConnectionFactory);
2319        let pool = Pool::new(config, factory)?;
2320
2321        let conn = pool.acquire().await?;
2322        pool.release(conn).await;
2323
2324        // 等待一下确保空闲超时
2325        tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
2326
2327        pool.reap_idle().await;
2328        let status = pool.status().await;
2329        assert_eq!(status.idle, 0);
2330        Ok(())
2331    }
2332
2333    /// H-7 验证:acquire_timeout 默认 30s
2334    ///
2335    /// PoolConfig::default().acquire_timeout == 30s
2336    /// Pool::acquire() 内部使用 `deadline = Instant::now() + acquire_timeout`
2337    /// 超时后返回 `PoolError::Timeout`。
2338    #[tokio::test]
2339    async fn test_h7_acquire_timeout_default_30s() {
2340        let config = PoolConfig::default();
2341        assert_eq!(
2342            config.acquire_timeout,
2343            Duration::from_secs(30),
2344            "H-7: acquire_timeout 默认应为 30s"
2345        );
2346    }
2347
2348    /// H-7 验证:acquire_timeout 可通过 builder 配置
2349    #[tokio::test]
2350    async fn test_h7_acquire_timeout_configurable() -> Result<(), Box<dyn std::error::Error>> {
2351        let config = PoolConfigBuilder::new()
2352            .max_size(1)
2353            .acquire_timeout(5) // 5s
2354            .build()?;
2355        assert_eq!(config.acquire_timeout, Duration::from_secs(5));
2356
2357        // 创建 max_size=1 的池,acquire 一个连接(占满),第二次 acquire 应超时
2358        let factory = Arc::new(MockConnectionFactory);
2359        let pool = Pool::new(config, factory)?;
2360        let _conn1 = pool.acquire().await?;
2361
2362        // 第二次 acquire 应在 5s 后超时(这里用 1ms 超时配置加速测试)
2363        let fast_config = PoolConfigBuilder::new()
2364            .max_size(1)
2365            .acquire_timeout(0) // 立即超时(0s 超时;deadline 为 now)
2366            .build()?;
2367        // 注意:acquire_timeout(0) 是合法值,表示 deadline 为 now
2368        // 实际行为:第一次循环即检查 deadline,返回 Timeout
2369        let fast_pool = Pool::new(fast_config, Arc::new(MockConnectionFactory))?;
2370        let _fast_conn = fast_pool.acquire().await?; // 占满 max_size=1
2371        let result = fast_pool.acquire().await;
2372        assert!(
2373            matches!(result, Err(PoolError::Timeout)),
2374            "H-7: 应返回 Timeout"
2375        );
2376        Ok(())
2377    }
2378
2379    // ==================== M-7 健康检查测试 ====================
2380
2381    #[tokio::test]
2382    async fn test_m7_health_check_removes_nothing_when_all_healthy(
2383    ) -> Result<(), Box<dyn std::error::Error>> {
2384        // 所有连接健康时,health_check 应返回 0
2385        let config = PoolConfigBuilder::new().max_size(5).build()?;
2386        let factory = Arc::new(MockConnectionFactory);
2387        let pool = Pool::new(config, factory)?;
2388
2389        // 创建 3 个连接并归还到池中
2390        let conn1 = pool.acquire().await?;
2391        let conn2 = pool.acquire().await?;
2392        let conn3 = pool.acquire().await?;
2393        pool.release(conn1).await;
2394        pool.release(conn2).await;
2395        pool.release(conn3).await;
2396
2397        let removed = pool.health_check().await;
2398        assert_eq!(removed, 0, "Healthy connections should not be removed");
2399
2400        let status = pool.status().await;
2401        assert_eq!(status.idle, 3);
2402        assert_eq!(status.active, 3);
2403        Ok(())
2404    }
2405
2406    #[tokio::test]
2407    async fn test_m7_health_check_returns_zero_for_empty_pool(
2408    ) -> Result<(), Box<dyn std::error::Error>> {
2409        let config = PoolConfigBuilder::new().max_size(5).build()?;
2410        let factory = Arc::new(MockConnectionFactory);
2411        let pool = Pool::new(config, factory)?;
2412
2413        let removed = pool.health_check().await;
2414        assert_eq!(removed, 0);
2415        Ok(())
2416    }
2417
2418    // ==================== 生产 Bug 复现测试 ====================
2419
2420    /// 可追踪创建次数的连接工厂
2421    struct CountingFactory {
2422        count: AtomicU32,
2423    }
2424
2425    impl CountingFactory {
2426        fn new() -> Self {
2427            Self {
2428                count: AtomicU32::new(0),
2429            }
2430        }
2431        fn created_count(&self) -> u32 {
2432            self.count.load(Ordering::SeqCst)
2433        }
2434    }
2435
2436    #[async_trait]
2437    impl ConnectionFactory for CountingFactory {
2438        async fn create(&self) -> Result<Box<dyn Connection>, crate::DbError> {
2439            self.count.fetch_add(1, Ordering::SeqCst);
2440            Ok(Box::new(MockConnection::new()))
2441        }
2442    }
2443
2444    /// 生产 Bug 复现:release() 重置 created_at 导致连接永不过期
2445    ///
2446    /// 症状:生产环境运行 30 分钟后间歇性 "connection timeout"
2447    /// 根因:release() 中 created_at 被重置为 now(),max_lifetime 检查永远不触发
2448    /// 期望:超过 max_lifetime 的连接应被回收并创建新连接
2449    #[tokio::test]
2450    async fn test_production_bug_max_lifetime_never_expires(
2451    ) -> Result<(), Box<dyn std::error::Error>> {
2452        // 注意:PoolConfigBuilder::max_lifetime() 接受秒,这里需要毫秒级精度
2453        // 所以直接构造 PoolConfig
2454        let config = PoolConfig {
2455            max_size: 5,
2456            min_idle: 0,
2457            acquire_timeout: Duration::from_secs(30),
2458            idle_timeout: Duration::from_secs(600),
2459            max_lifetime: Duration::from_millis(100), // 100ms
2460            connection_timeout: Duration::from_secs(10),
2461            tls: None,
2462            query_timeout: None,
2463            max_rows: None,
2464            memory_limit: None,
2465            on_event: None,
2466            test_before_acquire: false,
2467            prewarm: false,
2468        };
2469        let factory = Arc::new(CountingFactory::new());
2470        let pool = Pool::new(config, factory.clone())?;
2471
2472        // 1. 创建连接
2473        let conn = pool.acquire().await?;
2474        assert_eq!(factory.created_count(), 1, "应创建 1 个连接");
2475
2476        // 2. 归还连接(bug:重置 created_at)
2477        pool.release(conn).await;
2478
2479        // 3. 等待超过 max_lifetime
2480        tokio::time::sleep(Duration::from_millis(150)).await;
2481
2482        // 4. 再次获取 — 应检测到连接过期,创建新连接
2483        let conn2 = pool.acquire().await?;
2484
2485        // 5. 验证:如果 bug 存在,factory.created_count() 仍为 1(连接被复用,未过期)
2486        //         如果修复,factory.created_count() 应为 2(旧连接过期,创建新连接)
2487        assert_eq!(
2488            factory.created_count(),
2489            2,
2490            "超过 max_lifetime 后应创建新连接(旧连接应被回收)"
2491        );
2492
2493        pool.release(conn2).await;
2494        Ok(())
2495    }
2496
2497    // ==================== PooledConnection::Drop 自动归还测试 ====================
2498
2499    /// 验证 PooledConnection drop 时自动归还连接到池
2500    ///
2501    /// 修复前:PooledConnection 未实现 Drop,drop 时连接丢失,池耗尽
2502    /// 修复后:Drop 时 spawn 异步 release,连接自动归还
2503    #[tokio::test]
2504    async fn test_drop_auto_release_connection() -> Result<(), Box<dyn std::error::Error>> {
2505        let config = PoolConfigBuilder::new().max_size(2).build()?;
2506        let factory = Arc::new(CountingFactory::new());
2507        let pool = Pool::new(config, factory.clone())?;
2508
2509        // 1. acquire 一个连接(不显式 release)
2510        {
2511            let _conn = pool.acquire().await?;
2512            assert_eq!(factory.created_count(), 1, "应创建 1 个连接");
2513            let status = pool.status().await;
2514            assert_eq!(status.active, 1, "active 应为 1");
2515            assert_eq!(status.idle, 0, "idle 应为 0");
2516            // _conn 在此 drop
2517        }
2518
2519        // 2. 等待 Drop spawn 的异步 release 完成
2520        tokio::time::sleep(Duration::from_millis(50)).await;
2521
2522        // 3. 验证连接已自动归还到 idle 队列
2523        let status = pool.status().await;
2524        assert_eq!(status.idle, 1, "Drop 后连接应自动归还,idle 应为 1");
2525        assert_eq!(status.active, 1, "total_count 应为 1");
2526        assert_eq!(factory.created_count(), 1, "应复用归还的连接,不创建新连接");
2527        Ok(())
2528    }
2529
2530    /// 验证 Drop 自动归还后,连接可被再次 acquire 复用
2531    #[tokio::test]
2532    async fn test_drop_auto_release_then_reuse() -> Result<(), Box<dyn std::error::Error>> {
2533        let config = PoolConfigBuilder::new().max_size(1).build()?;
2534        let factory = Arc::new(CountingFactory::new());
2535        let pool = Pool::new(config, factory.clone())?;
2536
2537        // max_size=1,如果 Drop 不归还,第二次 acquire 会超时
2538        {
2539            let _conn = pool.acquire().await?;
2540        }
2541
2542        // 等待 Drop spawn 的 release 完成
2543        tokio::time::sleep(Duration::from_millis(50)).await;
2544
2545        // 再次 acquire 应复用归还的连接,不创建新连接
2546        let conn = pool.acquire().await?;
2547        assert_eq!(factory.created_count(), 1, "应复用归还的连接,不创建新连接");
2548
2549        pool.release(conn).await;
2550        Ok(())
2551    }
2552
2553    /// 验证 into_inner 后 Drop 不归还(连接被消费)
2554    #[tokio::test]
2555    async fn test_into_inner_does_not_return_to_pool() -> Result<(), Box<dyn std::error::Error>> {
2556        let config = PoolConfigBuilder::new().max_size(2).build()?;
2557        let factory = Arc::new(CountingFactory::new());
2558        let pool = Pool::new(config, factory.clone())?;
2559
2560        let conn = pool.acquire().await?;
2561        assert_eq!(factory.created_count(), 1);
2562
2563        // into_inner 消费连接,pool 字段设为 None
2564        let _raw_conn = conn.into_inner();
2565
2566        // 等待一段时间,确保不会有 Drop spawn
2567        tokio::time::sleep(Duration::from_millis(50)).await;
2568
2569        let status = pool.status().await;
2570        assert_eq!(status.idle, 0, "into_inner 后连接不应归还");
2571        assert_eq!(status.active, 1, "total_count 仍为 1(连接被外部持有)");
2572        Ok(())
2573    }
2574
2575    /// 验证显式 release 后 Drop 不会重复归还
2576    #[tokio::test]
2577    async fn test_explicit_release_no_double_return() -> Result<(), Box<dyn std::error::Error>> {
2578        let config = PoolConfigBuilder::new().max_size(2).build()?;
2579        let factory = Arc::new(CountingFactory::new());
2580        let pool = Pool::new(config, factory.clone())?;
2581
2582        let conn = pool.acquire().await?;
2583        pool.release(conn).await;
2584
2585        let status = pool.status().await;
2586        assert_eq!(status.idle, 1, "release 后 idle 应为 1");
2587
2588        // 再次 acquire + release 验证不会重复
2589        let conn = pool.acquire().await?;
2590        pool.release(conn).await;
2591
2592        let status = pool.status().await;
2593        assert_eq!(status.idle, 1, "再次 release 后 idle 仍应为 1(不重复)");
2594        assert_eq!(status.active, 1, "total_count 应为 1");
2595        Ok(())
2596    }
2597
2598    // ========================================================================
2599    // G-SX-4:query_stream 游标流式查询测试
2600    // ========================================================================
2601
2602    /// 带预设行数据的模拟连接,用于测试 `query_stream` 默认实现。
2603    struct CursorMockConn {
2604        rows: QueryRows,
2605        call_count: usize,
2606    }
2607
2608    impl CursorMockConn {
2609        fn new(rows: QueryRows) -> Self {
2610            Self {
2611                rows,
2612                call_count: 0,
2613            }
2614        }
2615    }
2616
2617    impl Connection for CursorMockConn {
2618        fn execute<'a>(
2619            &'a mut self,
2620            _sql: &'a str,
2621        ) -> Pin<Box<dyn Future<Output = Result<u64, crate::DbError>> + Send + 'a>> {
2622            Box::pin(async move { Ok(1) })
2623        }
2624
2625        fn query<'a>(
2626            &'a mut self,
2627            _sql: &'a str,
2628        ) -> Pin<Box<dyn Future<Output = Result<QueryRows, crate::DbError>> + Send + 'a>> {
2629            Box::pin(async move {
2630                self.call_count += 1;
2631                Ok(self.rows.clone())
2632            })
2633        }
2634
2635        fn begin_transaction<'a>(
2636            &'a mut self,
2637        ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>> {
2638            Box::pin(async move { Ok(()) })
2639        }
2640
2641        fn commit<'a>(
2642            &'a mut self,
2643        ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>> {
2644            Box::pin(async move { Ok(()) })
2645        }
2646
2647        fn rollback<'a>(
2648            &'a mut self,
2649        ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>> {
2650            Box::pin(async move { Ok(()) })
2651        }
2652
2653        fn is_connected(&self) -> bool {
2654            true
2655        }
2656
2657        fn ping<'a>(&'a mut self) -> Pin<Box<dyn Future<Output = bool> + Send + 'a>> {
2658            Box::pin(async move { true })
2659        }
2660
2661        fn close<'a>(
2662            &'a mut self,
2663        ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>> {
2664            Box::pin(async move { Ok(()) })
2665        }
2666    }
2667
2668    /// 模拟游标适配器:覆盖 `query_stream` 以逐行 yield,而非全量收集。
2669    struct CursorOverrideMockConn {
2670        rows: Vec<crate::value::Value>,
2671        yielded: usize,
2672    }
2673
2674    impl CursorOverrideMockConn {
2675        fn new(rows: Vec<crate::value::Value>) -> Self {
2676            Self { rows, yielded: 0 }
2677        }
2678    }
2679
2680    impl Connection for CursorOverrideMockConn {
2681        fn execute<'a>(
2682            &'a mut self,
2683            _sql: &'a str,
2684        ) -> Pin<Box<dyn Future<Output = Result<u64, crate::DbError>> + Send + 'a>> {
2685            Box::pin(async move { Ok(1) })
2686        }
2687
2688        fn query<'a>(
2689            &'a mut self,
2690            _sql: &'a str,
2691        ) -> Pin<Box<dyn Future<Output = Result<QueryRows, crate::DbError>> + Send + 'a>> {
2692            // 全量收集实现(不应被 cursor override 调用)
2693            Box::pin(async move {
2694                Ok(self
2695                    .rows
2696                    .iter()
2697                    .map(|v| {
2698                        let mut m = std::collections::HashMap::new();
2699                        m.insert("v".to_string(), v.clone());
2700                        m
2701                    })
2702                    .collect())
2703            })
2704        }
2705
2706        /// G-SX-4:覆盖 query_stream,逐行 yield 模拟真游标
2707        fn query_stream<'a>(
2708            &'a mut self,
2709            _sql: &'a str,
2710        ) -> Pin<Box<dyn futures::Stream<Item = QueryStreamItem> + Send + 'a>> {
2711            Box::pin(futures::stream::iter(
2712                self.rows
2713                    .iter()
2714                    .enumerate()
2715                    .map(|(i, v)| {
2716                        self.yielded = i + 1;
2717                        let mut m = std::collections::HashMap::new();
2718                        m.insert("v".to_string(), v.clone());
2719                        Ok(m)
2720                    })
2721                    .collect::<Vec<_>>(),
2722            ))
2723        }
2724
2725        fn begin_transaction<'a>(
2726            &'a mut self,
2727        ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>> {
2728            Box::pin(async move { Ok(()) })
2729        }
2730
2731        fn commit<'a>(
2732            &'a mut self,
2733        ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>> {
2734            Box::pin(async move { Ok(()) })
2735        }
2736
2737        fn rollback<'a>(
2738            &'a mut self,
2739        ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>> {
2740            Box::pin(async move { Ok(()) })
2741        }
2742
2743        fn is_connected(&self) -> bool {
2744            true
2745        }
2746
2747        fn ping<'a>(&'a mut self) -> Pin<Box<dyn Future<Output = bool> + Send + 'a>> {
2748            Box::pin(async move { true })
2749        }
2750
2751        fn close<'a>(
2752            &'a mut self,
2753        ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>> {
2754            Box::pin(async move { Ok(()) })
2755        }
2756    }
2757
2758    /// G-SX-4 测试 1:默认 query_stream 逐行 yield 全量结果
2759    #[tokio::test]
2760    async fn test_query_stream_default_impl_yields_all_rows() {
2761        use futures::StreamExt;
2762        let rows: QueryRows = vec![
2763            std::collections::HashMap::from([
2764                ("id".to_string(), crate::value::Value::I64(1)),
2765                (
2766                    "name".to_string(),
2767                    crate::value::Value::String("alice".to_string()),
2768                ),
2769            ]),
2770            std::collections::HashMap::from([
2771                ("id".to_string(), crate::value::Value::I64(2)),
2772                (
2773                    "name".to_string(),
2774                    crate::value::Value::String("bob".to_string()),
2775                ),
2776            ]),
2777            std::collections::HashMap::from([
2778                ("id".to_string(), crate::value::Value::I64(3)),
2779                (
2780                    "name".to_string(),
2781                    crate::value::Value::String("carol".to_string()),
2782                ),
2783            ]),
2784        ];
2785        let mut conn = CursorMockConn::new(rows);
2786        let mut stream = conn.query_stream("SELECT id, name FROM users");
2787        let mut received: Vec<QueryStreamItem> = Vec::new();
2788        while let Some(item) = stream.next().await {
2789            received.push(item);
2790        }
2791        assert_eq!(received.len(), 3, "应收到 3 行");
2792        assert!(received.iter().all(|r| r.is_ok()), "所有项应为 Ok");
2793        drop(stream);
2794        assert_eq!(conn.call_count, 1, "默认实现应调用 query() 一次");
2795    }
2796
2797    /// G-SX-4 测试 2:默认 query_stream 空结果集
2798    #[tokio::test]
2799    async fn test_query_stream_default_empty_result() {
2800        use futures::StreamExt;
2801        let mut conn = CursorMockConn::new(Vec::new());
2802        let mut stream = conn.query_stream("SELECT * FROM empty_table");
2803        let mut count = 0;
2804        while let Some(_item) = stream.next().await {
2805            count += 1;
2806        }
2807        assert_eq!(count, 0, "空结果集应产生 0 项");
2808    }
2809
2810    /// G-SX-4 测试 3:默认 query_stream 错误传播
2811    #[tokio::test]
2812    async fn test_query_stream_default_error_propagation() {
2813        use futures::StreamExt;
2814        // 创建一个会返回错误的 mock
2815        struct ErrorMockConn;
2816        impl Connection for ErrorMockConn {
2817            fn execute<'a>(
2818                &'a mut self,
2819                _sql: &'a str,
2820            ) -> Pin<Box<dyn Future<Output = Result<u64, crate::DbError>> + Send + 'a>>
2821            {
2822                Box::pin(async move { Ok(1) })
2823            }
2824            fn query<'a>(
2825                &'a mut self,
2826                _sql: &'a str,
2827            ) -> Pin<Box<dyn Future<Output = Result<QueryRows, crate::DbError>> + Send + 'a>>
2828            {
2829                Box::pin(async move { Err(crate::DbError::Internal("query failed".to_string())) })
2830            }
2831            fn begin_transaction<'a>(
2832                &'a mut self,
2833            ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>> {
2834                Box::pin(async move { Ok(()) })
2835            }
2836            fn commit<'a>(
2837                &'a mut self,
2838            ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>> {
2839                Box::pin(async move { Ok(()) })
2840            }
2841            fn rollback<'a>(
2842                &'a mut self,
2843            ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>> {
2844                Box::pin(async move { Ok(()) })
2845            }
2846            fn is_connected(&self) -> bool {
2847                true
2848            }
2849            fn ping<'a>(&'a mut self) -> Pin<Box<dyn Future<Output = bool> + Send + 'a>> {
2850                Box::pin(async move { true })
2851            }
2852            fn close<'a>(
2853                &'a mut self,
2854            ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>> {
2855                Box::pin(async move { Ok(()) })
2856            }
2857        }
2858        let mut conn = ErrorMockConn;
2859        let mut stream = conn.query_stream("SELECT * FROM bad_table");
2860        let item = stream.next().await;
2861        assert!(item.is_some(), "应产生一项");
2862        assert!(item.unwrap().is_err(), "该项应为 Err");
2863    }
2864
2865    /// G-SX-4 测试 4:覆盖 query_stream 的适配器逐行 yield(模拟真游标)
2866    #[tokio::test]
2867    async fn test_query_stream_override_yields_rows_one_by_one() {
2868        use futures::StreamExt;
2869        let rows = vec![
2870            crate::value::Value::I64(10),
2871            crate::value::Value::I64(20),
2872            crate::value::Value::I64(30),
2873            crate::value::Value::I64(40),
2874            crate::value::Value::I64(50),
2875        ];
2876        let mut conn = CursorOverrideMockConn::new(rows);
2877        let values: Vec<i64> = {
2878            let mut stream = conn.query_stream("SELECT v FROM seq");
2879            let mut vals: Vec<i64> = Vec::new();
2880            while let Some(Ok(row)) = stream.next().await {
2881                if let crate::value::Value::I64(v) = row.get("v").unwrap() {
2882                    vals.push(*v);
2883                }
2884            }
2885            vals
2886        };
2887        assert_eq!(values, vec![10, 20, 30, 40, 50], "应按顺序收到全部 5 行");
2888        assert_eq!(conn.yielded, 5, "应逐行 yield 5 次(真游标覆盖)");
2889    }
2890
2891    /// G-SX-4 测试 5:覆盖 query_stream 提前 drop 流(消费者中断)
2892    #[tokio::test]
2893    async fn test_query_stream_override_early_drop() {
2894        use futures::StreamExt;
2895        let rows = vec![
2896            crate::value::Value::I64(1),
2897            crate::value::Value::I64(2),
2898            crate::value::Value::I64(3),
2899        ];
2900        let mut conn = CursorOverrideMockConn::new(rows);
2901        {
2902            let mut stream = conn.query_stream("SELECT v FROM seq");
2903            let first = stream.next().await;
2904            assert!(first.is_some(), "第一项应存在");
2905            // 提前 drop stream — 模拟消费者中断
2906            drop(stream);
2907        }
2908        // 连接仍可用
2909        assert!(conn.is_connected(), "提前 drop 流后连接仍应可用");
2910    }
2911
2912    /// TASK-021:连接池预热测试
2913    #[tokio::test]
2914    async fn test_pool_prewarm() -> Result<(), Box<dyn std::error::Error>> {
2915        use std::sync::atomic::AtomicU32;
2916
2917        // 创建可计数的连接工厂
2918        let create_count = Arc::new(AtomicU32::new(0));
2919        let create_count_clone = create_count.clone();
2920
2921        struct CountingFactory {
2922            count: Arc<AtomicU32>,
2923        }
2924
2925        #[async_trait]
2926        impl ConnectionFactory for CountingFactory {
2927            async fn create(&self) -> Result<Box<dyn Connection>, crate::DbError> {
2928                self.count.fetch_add(1, Ordering::SeqCst);
2929                Ok(Box::new(MockConnection::new()))
2930            }
2931        }
2932
2933        // 配置:max_size=10, min_idle=5, prewarm=true
2934        let config = PoolConfigBuilder::new()
2935            .max_size(10)
2936            .min_idle(5)
2937            .prewarm(true)
2938            .build()?;
2939
2940        let factory = Arc::new(CountingFactory {
2941            count: create_count_clone,
2942        });
2943
2944        let pool = Pool::new(config, factory)?;
2945
2946        // 预热前:空闲连接为 0
2947        let status_before = pool.status().await;
2948        assert_eq!(status_before.idle, 0, "预热前 idle 应为 0");
2949
2950        // 执行预热
2951        pool.prewarm().await;
2952
2953        // 预热后:空闲连接应 >= min_idle(5)
2954        let status_after = pool.status().await;
2955        assert!(
2956            status_after.idle >= 5,
2957            "预热后 idle 应 >= 5,实际: {}",
2958            status_after.idle
2959        );
2960
2961        // 验证工厂被调用了 5 次(min_idle)
2962        assert_eq!(
2963            create_count.load(Ordering::SeqCst),
2964            5,
2965            "工厂应被调用 5 次(min_idle)"
2966        );
2967
2968        Ok(())
2969    }
2970
2971    /// TASK-021:预热失败不阻断池创建
2972    #[tokio::test]
2973    async fn test_pool_prewarm_failure_non_blocking() -> Result<(), Box<dyn std::error::Error>> {
2974        use std::sync::atomic::AtomicBool;
2975
2976        struct FailingFactory {
2977            failed: Arc<AtomicBool>,
2978        }
2979
2980        #[async_trait]
2981        impl ConnectionFactory for FailingFactory {
2982            async fn create(&self) -> Result<Box<dyn Connection>, crate::DbError> {
2983                self.failed.store(true, Ordering::SeqCst);
2984                // 模拟连接失败
2985                Err(crate::DbError::Internal(
2986                    "simulated connection failure".to_string(),
2987                ))
2988            }
2989        }
2990
2991        let failed = Arc::new(AtomicBool::new(false));
2992        let mut config = PoolConfigBuilder::new()
2993            .max_size(10)
2994            .min_idle(3)
2995            .prewarm(true)
2996            .build()?;
2997        config.connection_timeout = std::time::Duration::from_secs(1); // 缩短超时以加快测试
2998
2999        let factory = Arc::new(FailingFactory {
3000            failed: failed.clone(),
3001        });
3002
3003        // 池创建应成功(即使预热失败)
3004        let pool = Pool::new(config, factory)?;
3005        pool.prewarm().await; // 预热失败不应 panic
3006
3007        // 验证工厂被调用了 3 次(尝试预热 3 个连接)
3008        assert!(failed.load(Ordering::SeqCst), "工厂应被调用且失败");
3009
3010        // 池仍然可用(acquire 会尝试创建新连接)
3011        let status = pool.status().await;
3012        assert_eq!(status.max, 10, "池配置应正常");
3013
3014        Ok(())
3015    }
3016
3017    /// TASK-021:prewarm=false 时预热不执行
3018    #[tokio::test]
3019    async fn test_pool_prewarm_disabled() -> Result<(), Box<dyn std::error::Error>> {
3020        use std::sync::atomic::AtomicU32;
3021
3022        let create_count = Arc::new(AtomicU32::new(0));
3023        let create_count_clone = create_count.clone();
3024
3025        struct CountingFactory {
3026            count: Arc<AtomicU32>,
3027        }
3028
3029        #[async_trait]
3030        impl ConnectionFactory for CountingFactory {
3031            async fn create(&self) -> Result<Box<dyn Connection>, crate::DbError> {
3032                self.count.fetch_add(1, Ordering::SeqCst);
3033                Ok(Box::new(MockConnection::new()))
3034            }
3035        }
3036
3037        // 配置:prewarm=false
3038        let config = PoolConfigBuilder::new()
3039            .max_size(10)
3040            .min_idle(5)
3041            .prewarm(false) // 禁用预热
3042            .build()?;
3043
3044        let factory = Arc::new(CountingFactory {
3045            count: create_count_clone,
3046        });
3047
3048        let pool = Pool::new(config, factory)?;
3049        pool.prewarm().await; // 应直接返回,不创建连接
3050
3051        // 验证工厂未被调用
3052        assert_eq!(
3053            create_count.load(Ordering::SeqCst),
3054            0,
3055            "prewarm=false 时工厂不应被调用"
3056        );
3057
3058        let status = pool.status().await;
3059        assert_eq!(status.idle, 0, "idle 应为 0");
3060
3061        Ok(())
3062    }
3063
3064    /// v3.2.0:Pool::new_async with prewarm=true 预热后 idle >= min_idle
3065    #[tokio::test]
3066    async fn test_pool_new_async_with_prewarm() -> Result<(), Box<dyn std::error::Error>> {
3067        use std::sync::atomic::AtomicU32;
3068
3069        let create_count = Arc::new(AtomicU32::new(0));
3070        let create_count_clone = create_count.clone();
3071
3072        struct CountingFactory {
3073            count: Arc<AtomicU32>,
3074        }
3075
3076        #[async_trait]
3077        impl ConnectionFactory for CountingFactory {
3078            async fn create(&self) -> Result<Box<dyn Connection>, crate::DbError> {
3079                self.count.fetch_add(1, Ordering::SeqCst);
3080                Ok(Box::new(MockConnection::new()))
3081            }
3082        }
3083
3084        let config = PoolConfigBuilder::new()
3085            .max_size(10)
3086            .min_idle(5)
3087            .prewarm(true)
3088            .build()?;
3089
3090        let factory = Arc::new(CountingFactory {
3091            count: create_count_clone,
3092        });
3093
3094        let pool = Pool::new_async(config, factory).await?;
3095
3096        let status = pool.status().await;
3097        assert!(
3098            status.idle >= 5,
3099            "new_async prewarm=true 后 idle 应 >= 5,实际: {}",
3100            status.idle
3101        );
3102        assert_eq!(create_count.load(Ordering::SeqCst), 5, "工厂应被调用 5 次");
3103
3104        Ok(())
3105    }
3106
3107    /// v3.2.0:Pool::new_async with prewarm=false 等同 Pool::new
3108    #[tokio::test]
3109    async fn test_pool_new_async_without_prewarm() -> Result<(), Box<dyn std::error::Error>> {
3110        use std::sync::atomic::AtomicU32;
3111
3112        let create_count = Arc::new(AtomicU32::new(0));
3113        let create_count_clone = create_count.clone();
3114
3115        struct CountingFactory {
3116            count: Arc<AtomicU32>,
3117        }
3118
3119        #[async_trait]
3120        impl ConnectionFactory for CountingFactory {
3121            async fn create(&self) -> Result<Box<dyn Connection>, crate::DbError> {
3122                self.count.fetch_add(1, Ordering::SeqCst);
3123                Ok(Box::new(MockConnection::new()))
3124            }
3125        }
3126
3127        let config = PoolConfigBuilder::new()
3128            .max_size(10)
3129            .min_idle(5)
3130            .prewarm(false)
3131            .build()?;
3132
3133        let factory = Arc::new(CountingFactory {
3134            count: create_count_clone,
3135        });
3136
3137        let pool = Pool::new_async(config, factory).await?;
3138
3139        let status = pool.status().await;
3140        assert_eq!(status.idle, 0, "prewarm=false 时 idle 应为 0");
3141        assert_eq!(create_count.load(Ordering::SeqCst), 0, "工厂不应被调用");
3142
3143        Ok(())
3144    }
3145
3146    /// v3.2.0:Pool::new_async 预热失败不阻断池创建
3147    #[tokio::test]
3148    async fn test_pool_new_async_failure_non_blocking() -> Result<(), Box<dyn std::error::Error>> {
3149        struct FailingFactory;
3150
3151        #[async_trait]
3152        impl ConnectionFactory for FailingFactory {
3153            async fn create(&self) -> Result<Box<dyn Connection>, crate::DbError> {
3154                Err(crate::DbError::Internal("simulated failure".to_string()))
3155            }
3156        }
3157
3158        let mut config = PoolConfigBuilder::new()
3159            .max_size(10)
3160            .min_idle(3)
3161            .prewarm(true)
3162            .build()?;
3163        config.connection_timeout = std::time::Duration::from_secs(1);
3164
3165        let pool = Pool::new_async(config, Arc::new(FailingFactory)).await?;
3166
3167        let status = pool.status().await;
3168        assert_eq!(status.max, 10, "池配置应正常");
3169
3170        Ok(())
3171    }
3172
3173    /// v3.2.0:progressive_prewarm 分批建连
3174    #[cfg(feature = "auto-prewarm")]
3175    #[tokio::test]
3176    async fn test_pool_progressive_prewarm() -> Result<(), Box<dyn std::error::Error>> {
3177        use std::sync::atomic::AtomicU32;
3178
3179        let create_count = Arc::new(AtomicU32::new(0));
3180        let create_count_clone = create_count.clone();
3181
3182        struct CountingFactory {
3183            count: Arc<AtomicU32>,
3184        }
3185
3186        #[async_trait]
3187        impl ConnectionFactory for CountingFactory {
3188            async fn create(&self) -> Result<Box<dyn Connection>, crate::DbError> {
3189                self.count.fetch_add(1, Ordering::SeqCst);
3190                Ok(Box::new(MockConnection::new()))
3191            }
3192        }
3193
3194        let config = PoolConfigBuilder::new()
3195            .max_size(20)
3196            .min_idle(6)
3197            .prewarm(true)
3198            .build()?;
3199
3200        let factory = Arc::new(CountingFactory {
3201            count: create_count_clone,
3202        });
3203
3204        let pool = Pool::new(config, factory)?;
3205
3206        let progress = crate::prewarm::PrewarmProgress::new(6);
3207        pool.progressive_prewarm(
3208            2,
3209            std::time::Duration::from_millis(5),
3210            std::time::Duration::from_secs(10),
3211            &progress,
3212        )
3213        .await;
3214
3215        let snap = progress.snapshot();
3216        assert!(
3217            snap.warmed >= 6,
3218            "progressive_prewarm 后 warmed 应 >= 6,实际: {}",
3219            snap.warmed
3220        );
3221        assert!(snap.is_completed, "应标记完成");
3222        assert_eq!(create_count.load(Ordering::SeqCst), 6, "工厂应被调用 6 次");
3223
3224        let status = pool.status().await;
3225        assert!(status.idle >= 6, "池中 idle 应 >= 6");
3226
3227        Ok(())
3228    }
3229
3230    /// v3.2.0:progressive_prewarm total_timeout=0 立即停止
3231    #[cfg(feature = "auto-prewarm")]
3232    #[tokio::test]
3233    async fn test_pool_progressive_prewarm_timeout_zero() -> Result<(), Box<dyn std::error::Error>>
3234    {
3235        use std::sync::atomic::AtomicU32;
3236
3237        let create_count = Arc::new(AtomicU32::new(0));
3238        let create_count_clone = create_count.clone();
3239
3240        struct CountingFactory {
3241            count: Arc<AtomicU32>,
3242        }
3243
3244        #[async_trait]
3245        impl ConnectionFactory for CountingFactory {
3246            async fn create(&self) -> Result<Box<dyn Connection>, crate::DbError> {
3247                self.count.fetch_add(1, Ordering::SeqCst);
3248                Ok(Box::new(MockConnection::new()))
3249            }
3250        }
3251
3252        let config = PoolConfigBuilder::new()
3253            .max_size(20)
3254            .min_idle(10)
3255            .prewarm(true)
3256            .build()?;
3257
3258        let factory = Arc::new(CountingFactory {
3259            count: create_count_clone,
3260        });
3261
3262        let pool = Pool::new(config, factory)?;
3263
3264        let progress = crate::prewarm::PrewarmProgress::new(10);
3265        pool.progressive_prewarm(
3266            2,
3267            std::time::Duration::from_millis(5),
3268            std::time::Duration::ZERO,
3269            &progress,
3270        )
3271        .await;
3272
3273        let snap = progress.snapshot();
3274        assert!(snap.is_completed, "应标记完成");
3275        assert!(
3276            snap.warmed <= 2,
3277            "total_timeout=0 时最多建一批(batch_size=2),实际: {}",
3278            snap.warmed
3279        );
3280
3281        Ok(())
3282    }
3283
3284    /// v3.2.0:progressive_prewarm prewarm=false 时直接返回
3285    #[cfg(feature = "auto-prewarm")]
3286    #[tokio::test]
3287    async fn test_pool_progressive_prewarm_disabled() -> Result<(), Box<dyn std::error::Error>> {
3288        use std::sync::atomic::AtomicU32;
3289
3290        let create_count = Arc::new(AtomicU32::new(0));
3291        let create_count_clone = create_count.clone();
3292
3293        struct CountingFactory {
3294            count: Arc<AtomicU32>,
3295        }
3296
3297        #[async_trait]
3298        impl ConnectionFactory for CountingFactory {
3299            async fn create(&self) -> Result<Box<dyn Connection>, crate::DbError> {
3300                self.count.fetch_add(1, Ordering::SeqCst);
3301                Ok(Box::new(MockConnection::new()))
3302            }
3303        }
3304
3305        let config = PoolConfigBuilder::new()
3306            .max_size(20)
3307            .min_idle(10)
3308            .prewarm(false)
3309            .build()?;
3310
3311        let factory = Arc::new(CountingFactory {
3312            count: create_count_clone,
3313        });
3314
3315        let pool = Pool::new(config, factory)?;
3316
3317        let progress = crate::prewarm::PrewarmProgress::new(10);
3318        pool.progressive_prewarm(
3319            2,
3320            std::time::Duration::from_millis(5),
3321            std::time::Duration::from_secs(10),
3322            &progress,
3323        )
3324        .await;
3325
3326        let snap = progress.snapshot();
3327        assert!(snap.is_completed, "应标记完成");
3328        assert_eq!(snap.warmed, 0, "prewarm=false 时不应建连");
3329        assert_eq!(create_count.load(Ordering::SeqCst), 0, "工厂不应被调用");
3330
3331        Ok(())
3332    }
3333
3334    /// v3.2.0:progressive_prewarm 失败不阻断(failing factory)
3335    #[cfg(feature = "auto-prewarm")]
3336    #[tokio::test]
3337    async fn test_pool_progressive_prewarm_failure_non_blocking(
3338    ) -> Result<(), Box<dyn std::error::Error>> {
3339        struct FailingFactory;
3340
3341        #[async_trait]
3342        impl ConnectionFactory for FailingFactory {
3343            async fn create(&self) -> Result<Box<dyn Connection>, crate::DbError> {
3344                Err(crate::DbError::Internal("simulated failure".to_string()))
3345            }
3346        }
3347
3348        let mut config = PoolConfigBuilder::new()
3349            .max_size(20)
3350            .min_idle(5)
3351            .prewarm(true)
3352            .build()?;
3353        config.connection_timeout = std::time::Duration::from_secs(1);
3354
3355        let pool = Pool::new(config, Arc::new(FailingFactory))?;
3356
3357        let progress = crate::prewarm::PrewarmProgress::new(5);
3358        pool.progressive_prewarm(
3359            2,
3360            std::time::Duration::from_millis(5),
3361            std::time::Duration::from_secs(5),
3362            &progress,
3363        )
3364        .await;
3365
3366        let snap = progress.snapshot();
3367        assert!(snap.is_completed, "应标记完成");
3368        assert_eq!(snap.warmed, 0, "全部失败时 warmed=0");
3369        assert!(snap.failed > 0, "应有失败记录");
3370
3371        Ok(())
3372    }
3373
3374    /// Prometheus 风格统计:acquire/release 计数与连接创建计数
3375    #[tokio::test]
3376    async fn test_pool_metrics_acquire_release() -> Result<(), Box<dyn std::error::Error>> {
3377        let config = PoolConfigBuilder::new().max_size(10).build()?;
3378        let pool = Pool::new(config, Arc::new(MockConnectionFactory))?;
3379
3380        let metrics = pool.pool_metrics();
3381        assert_eq!(metrics.acquire_count, 0);
3382        assert_eq!(metrics.release_count, 0);
3383        assert_eq!(metrics.connection_created_count, 0);
3384
3385        let conn = pool.acquire().await?;
3386        let metrics = pool.pool_metrics();
3387        assert_eq!(metrics.acquire_count, 1);
3388        assert_eq!(metrics.connection_created_count, 1);
3389        assert_eq!(metrics.acquire_failed_count, 0);
3390
3391        pool.release(conn).await;
3392        let metrics = pool.pool_metrics();
3393        assert_eq!(metrics.release_count, 1);
3394        // 连接归还到空闲队列,未被关闭
3395        assert_eq!(metrics.connection_closed_count, 0);
3396
3397        Ok(())
3398    }
3399
3400    /// Prometheus 风格统计:获取失败计数(工厂创建连接失败)
3401    #[tokio::test]
3402    async fn test_pool_metrics_acquire_failed() -> Result<(), Box<dyn std::error::Error>> {
3403        struct FailingFactory;
3404
3405        #[async_trait]
3406        impl ConnectionFactory for FailingFactory {
3407            async fn create(&self) -> Result<Box<dyn Connection>, crate::DbError> {
3408                Err(crate::DbError::Internal("simulated failure".to_string()))
3409            }
3410        }
3411
3412        let config = PoolConfigBuilder::new().max_size(10).build()?;
3413        let pool = Pool::new(config, Arc::new(FailingFactory))?;
3414
3415        let result = pool.acquire().await;
3416        assert!(result.is_err());
3417
3418        let metrics = pool.pool_metrics();
3419        assert_eq!(metrics.acquire_failed_count, 1);
3420        assert_eq!(metrics.acquire_count, 0);
3421
3422        Ok(())
3423    }
3424
3425    /// Prometheus 风格统计:连接关闭计数(close_all 后空闲连接被关闭)
3426    #[tokio::test]
3427    async fn test_pool_metrics_connection_closed() -> Result<(), Box<dyn std::error::Error>> {
3428        let config = PoolConfigBuilder::new().max_size(10).build()?;
3429        let pool = Pool::new(config, Arc::new(MockConnectionFactory))?;
3430
3431        let conn = pool.acquire().await?;
3432        pool.release(conn).await;
3433
3434        let status = pool.status().await;
3435        assert_eq!(status.idle, 1);
3436
3437        pool.close_all().await;
3438
3439        let metrics = pool.pool_metrics();
3440        assert_eq!(metrics.connection_closed_count, 1);
3441        assert_eq!(metrics.connection_created_count, 1);
3442
3443        Ok(())
3444    }
3445
3446    /// Prometheus 风格统计:平均获取等待时长计算
3447    #[test]
3448    fn test_pool_metrics_average_wait_time() {
3449        let metrics = PoolMetrics {
3450            acquire_count: 4,
3451            acquire_failed_count: 1,
3452            acquire_wait_time: Duration::from_millis(200),
3453            release_count: 4,
3454            connection_created_count: 2,
3455            connection_closed_count: 0,
3456        };
3457        assert_eq!(
3458            metrics.average_acquire_wait_time(),
3459            Duration::from_millis(50)
3460        );
3461
3462        // 无成功获取时平均等待时长为 0
3463        let empty = PoolMetrics::default();
3464        assert_eq!(empty.average_acquire_wait_time(), Duration::ZERO);
3465    }
3466
3467    #[tokio::test]
3468    async fn test_shutdown_with_timeout_fast_return_when_empty() {
3469        let factory = Arc::new(MockConnectionFactory) as Arc<dyn ConnectionFactory>;
3470        let config = PoolConfigBuilder::new().max_size(4).build().unwrap();
3471        let pool = Pool::new(config, factory).unwrap();
3472        pool.shutdown_with_timeout(Duration::from_secs(1)).await;
3473        assert!(pool.closed.load(Ordering::SeqCst));
3474        assert_eq!(pool.total_count.load(Ordering::SeqCst), 0);
3475    }
3476
3477    #[tokio::test]
3478    async fn test_shutdown_delegates_to_shutdown_with_timeout() {
3479        let factory = Arc::new(MockConnectionFactory) as Arc<dyn ConnectionFactory>;
3480        let config = PoolConfigBuilder::new().max_size(4).build().unwrap();
3481        let pool = Pool::new(config, factory).unwrap();
3482        pool.shutdown().await;
3483        assert!(pool.closed.load(Ordering::SeqCst));
3484    }
3485
3486    #[tokio::test]
3487    async fn test_shutdown_with_timeout_idempotent() {
3488        let factory = Arc::new(MockConnectionFactory) as Arc<dyn ConnectionFactory>;
3489        let config = PoolConfigBuilder::new().max_size(4).build().unwrap();
3490        let pool = Pool::new(config, factory).unwrap();
3491        pool.shutdown_with_timeout(Duration::from_secs(1)).await;
3492        let count_after_first = pool.total_count.load(Ordering::SeqCst);
3493        pool.shutdown_with_timeout(Duration::from_secs(1)).await;
3494        let count_after_second = pool.total_count.load(Ordering::SeqCst);
3495        assert_eq!(count_after_first, count_after_second);
3496    }
3497
3498    #[tokio::test]
3499    async fn test_shutdown_with_timeout_rejects_new_acquire() {
3500        let factory = Arc::new(MockConnectionFactory) as Arc<dyn ConnectionFactory>;
3501        let config = PoolConfigBuilder::new().max_size(4).build().unwrap();
3502        let pool = Pool::new(config, factory).unwrap();
3503        pool.shutdown_with_timeout(Duration::from_secs(1)).await;
3504        let result = pool.acquire().await;
3505        assert!(result.is_err());
3506    }
3507}
3508
3509#[cfg(all(test, feature = "prod-pool-tuning"))]
3510mod pool_prod_tests {
3511    use super::*;
3512
3513    struct MockFactory;
3514
3515    #[async_trait]
3516    impl ConnectionFactory for MockFactory {
3517        async fn create(&self) -> Result<Box<dyn Connection>, crate::DbError> {
3518            Ok(Box::new(MockConn))
3519        }
3520    }
3521
3522    struct MockConn;
3523
3524    impl Connection for MockConn {
3525        fn execute<'a>(
3526            &'a mut self,
3527            _sql: &'a str,
3528        ) -> Pin<Box<dyn Future<Output = Result<u64, crate::DbError>> + Send + 'a>> {
3529            Box::pin(async move { Ok(1) })
3530        }
3531        fn query<'a>(
3532            &'a mut self,
3533            _sql: &'a str,
3534        ) -> Pin<
3535            Box<
3536                dyn Future<
3537                        Output = Result<
3538                            Vec<std::collections::HashMap<String, crate::value::Value>>,
3539                            crate::DbError,
3540                        >,
3541                    > + Send
3542                    + 'a,
3543            >,
3544        > {
3545            Box::pin(async move { Ok(vec![]) })
3546        }
3547        fn begin_transaction<'a>(
3548            &'a mut self,
3549        ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>> {
3550            Box::pin(async move { Ok(()) })
3551        }
3552        fn commit<'a>(
3553            &'a mut self,
3554        ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>> {
3555            Box::pin(async move { Ok(()) })
3556        }
3557        fn rollback<'a>(
3558            &'a mut self,
3559        ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>> {
3560            Box::pin(async move { Ok(()) })
3561        }
3562        fn is_connected(&self) -> bool {
3563            true
3564        }
3565        fn ping<'a>(&'a mut self) -> Pin<Box<dyn Future<Output = bool> + Send + 'a>> {
3566            Box::pin(async move { true })
3567        }
3568        fn close<'a>(
3569            &'a mut self,
3570        ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>> {
3571            Box::pin(async move { Ok(()) })
3572        }
3573    }
3574
3575    #[test]
3576    fn test_pool_prod_config_validate_ok() {
3577        let config = PoolProdConfig::new(
3578            50,
3579            Duration::from_secs(10),
3580            Duration::from_secs(600),
3581            Duration::from_secs(5),
3582            Duration::from_secs(30),
3583            5,
3584            true,
3585        );
3586        assert!(config.validate().is_ok());
3587    }
3588
3589    #[test]
3590    fn test_pool_prod_config_max_size_zero_rejected() {
3591        let config = PoolProdConfig::default();
3592        let mut c = config;
3593        c.max_size = 0;
3594        let err = c.validate().unwrap_err();
3595        assert!(err.to_string().contains("max_size must be positive"));
3596    }
3597
3598    #[test]
3599    fn test_pool_prod_config_min_idle_exceeds_max_size() {
3600        let config = PoolProdConfig::new(
3601            10,
3602            Duration::from_secs(10),
3603            Duration::from_secs(600),
3604            Duration::from_secs(5),
3605            Duration::from_secs(30),
3606            20,
3607            false,
3608        );
3609        let err = config.validate().unwrap_err();
3610        assert!(err.to_string().contains("min_idle cannot exceed max_size"));
3611    }
3612
3613    #[test]
3614    fn test_pool_prod_config_to_pool_config() {
3615        let config = PoolProdConfig::new(
3616            50,
3617            Duration::from_secs(10),
3618            Duration::from_secs(600),
3619            Duration::from_secs(5),
3620            Duration::from_secs(30),
3621            5,
3622            true,
3623        );
3624        let pool_config = config.to_pool_config();
3625        assert_eq!(pool_config.max_size, 50);
3626        assert_eq!(pool_config.min_idle, 5);
3627        assert_eq!(pool_config.acquire_timeout, Duration::from_secs(10));
3628        assert!(pool_config.prewarm);
3629    }
3630
3631    #[tokio::test]
3632    async fn test_pool_prod_config_runtime_resize() {
3633        let factory = Arc::new(MockFactory) as Arc<dyn ConnectionFactory>;
3634        let config = PoolProdConfig::default();
3635        let pool = Pool::new(config.to_pool_config(), factory).unwrap();
3636        assert_eq!(pool.max_size(), 100);
3637        pool.resize(50);
3638        assert_eq!(pool.max_size(), 50);
3639    }
3640}
3641
3642#[cfg(all(test, feature = "prod-leak-detection"))]
3643mod leak_prod_tests {
3644    use super::*;
3645
3646    #[test]
3647    fn test_leak_config_default() {
3648        let config = LeakDetectionConfig::default();
3649        assert!(!config.enabled);
3650        assert_eq!(config.interval, Duration::from_secs(60));
3651        assert_eq!(config.threshold, 5);
3652    }
3653
3654    #[test]
3655    fn test_leak_config_validate_ok() {
3656        let config =
3657            LeakDetectionConfig::new(true, Duration::from_secs(30), 10, Duration::from_secs(60));
3658        assert!(config.validate().is_ok());
3659    }
3660
3661    #[test]
3662    fn test_leak_config_interval_zero_rejected() {
3663        let config = LeakDetectionConfig::new(true, Duration::ZERO, 10, Duration::from_secs(60));
3664        assert!(config.validate().is_err());
3665    }
3666
3667    #[test]
3668    fn test_leak_report_empty() {
3669        let report = LeakReport::empty();
3670        assert_eq!(report.borrowed_count, 0);
3671        assert!(report.suspected_leaks.is_empty());
3672    }
3673}