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, 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    fn execute<'a>(
47        &'a mut self,
48        sql: &'a str,
49    ) -> Pin<Box<dyn Future<Output = Result<u64, crate::DbError>> + Send + 'a>>;
50    fn query<'a>(
51        &'a mut self,
52        sql: &'a str,
53    ) -> Pin<Box<dyn Future<Output = Result<QueryRows, crate::DbError>> + Send + 'a>>;
54    fn begin_transaction<'a>(
55        &'a mut self,
56    ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>>;
57    fn commit<'a>(
58        &'a mut self,
59    ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>>;
60    fn rollback<'a>(
61        &'a mut self,
62    ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>>;
63    fn is_connected(&self) -> bool;
64    fn ping<'a>(&'a mut self) -> Pin<Box<dyn Future<Output = bool> + Send + 'a>>;
65    fn close<'a>(
66        &'a mut self,
67    ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>>;
68
69    /// 参数绑定执行(INSERT/UPDATE/DELETE)
70    ///
71    /// 使用真实 prepared statement 绑定参数,避免 SQL 注入。
72    /// 默认实现返回 `NotImplemented` 错误;支持参数绑定的适配器
73    /// (如 sz-orm-oracle)应覆盖此方法。
74    fn execute_with_params<'a>(
75        &'a mut self,
76        sql: &'a str,
77        params: &'a [crate::value::Value],
78    ) -> Pin<Box<dyn Future<Output = Result<u64, crate::DbError>> + Send + 'a>> {
79        let _ = (sql, params);
80        Box::pin(async move {
81            Err(crate::DbError::Internal(
82                "execute_with_params not implemented for this adapter".to_string(),
83            ))
84        })
85    }
86
87    /// 参数绑定查询(SELECT)
88    ///
89    /// 使用真实 prepared statement 绑定参数,避免 SQL 注入。
90    /// 默认实现返回 `NotImplemented` 错误;支持参数绑定的适配器
91    /// (如 sz-orm-oracle)应覆盖此方法。
92    fn query_with_params<'a>(
93        &'a mut self,
94        sql: &'a str,
95        params: &'a [crate::value::Value],
96    ) -> Pin<Box<dyn Future<Output = Result<QueryRows, crate::DbError>> + Send + 'a>> {
97        let _ = (sql, params);
98        Box::pin(async move {
99            Err(crate::DbError::Internal(
100                "query_with_params not implemented for this adapter".to_string(),
101            ))
102        })
103    }
104
105    /// 位置式查询(SELECT):返回 `(列名, 按列顺序的值矩阵)`
106    ///
107    /// 绕过 `HashMap<String, Value>` 行映射,适用于 SELECT ALL 大结果集场景。
108    /// 默认实现返回 `NotImplemented` 错误;适配器可覆盖此方法以获得 30%~50% 性能提升。
109    fn query_values<'a>(
110        &'a mut self,
111        sql: &'a str,
112    ) -> Pin<Box<dyn Future<Output = Result<crate::value::QueryValues, crate::DbError>> + Send + 'a>>
113    {
114        let _ = sql;
115        Box::pin(async move {
116            Err(crate::DbError::Internal(
117                "query_values not implemented for this adapter".to_string(),
118            ))
119        })
120    }
121
122    /// 参数绑定位置式查询(SELECT):叠加 prepared statement + 位置式映射双重优化
123    ///
124    /// 默认实现返回 `NotImplemented` 错误;适配器可覆盖此方法以获得最佳性能。
125    fn query_values_with_params<'a>(
126        &'a mut self,
127        sql: &'a str,
128        params: &'a [crate::value::Value],
129    ) -> Pin<Box<dyn Future<Output = Result<crate::value::QueryValues, crate::DbError>> + Send + 'a>>
130    {
131        let _ = (sql, params);
132        Box::pin(async move {
133            Err(crate::DbError::Internal(
134                "query_values_with_params not implemented for this adapter".to_string(),
135            ))
136        })
137    }
138
139    /// 流式查询:返回逐行结果流
140    ///
141    /// 默认实现:通过 `query()` 获取全部行后,以
142    /// `futures::stream::iter` 逐行 yield,提供统一的流式消费接口。
143    /// 适合中小结果集;对超大结果集,支持原生游标的适配器应覆盖此方法。
144    ///
145    /// # 注意
146    ///
147    /// 此方法本身是同步的(返回 Stream),但内部通过 `futures::stream::once`
148    /// 异步获取数据后展开为逐行流。若适配器支持 sqlx `fetch()` 游标,
149    /// 覆盖此方法可获得真正的逐行拉取,避免大结果集内存峰值。
150    fn query_stream<'a>(
151        &'a mut self,
152        sql: &'a str,
153    ) -> Pin<Box<dyn futures::Stream<Item = QueryStreamItem> + Send + 'a>> {
154        // 克隆 sql 以脱离 &self 的生命周期
155        let sql_owned = sql.to_string();
156        // 使用 stream::once 异步执行查询,再 flat_map 为逐行流
157        let stream = futures::stream::once(async move { self.query(&sql_owned).await })
158            // 统一为 Vec 收集后再 iter:保证 match 两臂流类型一致(E0308 修复)
159            .map(|result| {
160                let items: Vec<QueryStreamItem> = match result {
161                    Ok(rows) => rows.into_iter().map(Ok).collect(),
162                    Err(e) => vec![Err(e)],
163                };
164                futures::stream::iter(items)
165            })
166            .flatten();
167        Box::pin(stream)
168    }
169
170    /// 游标式流式查询(P1-2):按 `batch_size` 分批拉取,避免大结果集内存峰值。
171    ///
172    /// 适用于无原生服务器端游标(或无法便捷暴露逐行拉取)的数据库:
173    /// - Oracle:`ROWNUM` 子查询包装(见 `cursor_stream::build_paged_query`);
174    /// - SQL Server:`OFFSET ... ROWS FETCH NEXT ... ROWS ONLY`。
175    ///
176    /// 默认实现退化为 [`Connection::query_stream`](全量拉取后逐行 yield);
177    /// Oracle/MSSQL 适配器应覆盖此方法,使用
178    /// `cursor_stream::stream_cursor_paged(conn, sql, DbType::Oracle, batch)`
179    /// 获得真正的分页游标流。
180    fn query_stream_cursor<'a>(
181        &'a mut self,
182        sql: &'a str,
183        _batch_size: usize,
184    ) -> Pin<Box<dyn futures::Stream<Item = QueryStreamItem> + Send + 'a>> {
185        self.query_stream(sql)
186    }
187
188    /// 批量执行多条 SQL(按顺序执行,返回累计影响行数)
189    ///
190    /// 默认实现循环调用 `execute`;适配器可覆盖此方法以利用数据库原生
191    /// 批量执行能力。
192    fn execute_batch<'a>(
193        &'a mut self,
194        sqls: &'a [String],
195    ) -> Pin<Box<dyn Future<Output = Result<u64, crate::DbError>> + Send + 'a>> {
196        Box::pin(async move {
197            let mut total = 0u64;
198            for sql in sqls {
199                total += self.execute(sql).await?;
200            }
201            Ok(total)
202        })
203    }
204
205    /// 批量插入(单条 SQL 多次参数绑定执行)
206    ///
207    /// 默认实现循环调用 `execute_with_params`;适配器可覆盖此方法
208    /// 以利用数据库原生批量 DML 能力(如 Oracle Array DML)。
209    fn execute_batch_params<'a>(
210        &'a mut self,
211        sql: &'a str,
212        params_batch: &'a [Vec<crate::value::Value>],
213    ) -> Pin<Box<dyn Future<Output = Result<u64, crate::DbError>> + Send + 'a>> {
214        Box::pin(async move {
215            let mut total = 0u64;
216            for params in params_batch {
217                total += self.execute_with_params(sql, params).await?;
218            }
219            Ok(total)
220        })
221    }
222}
223
224/// 连接池中的连接条目,记录创建时间和最后使用时间
225///
226/// - `created_at`:连接的原始创建时间,**不**随 acquire/release 重置,
227///   用于 `max_lifetime` 过期判定。
228/// - `last_used_at`:上次归还到池的时间,用于 `idle_timeout` 空闲超时判定。
229/// - `pool`:归属的连接池引用,Drop 时自动归还。`None` 表示无需归还
230///   (已通过 `release()`/`into_inner()` 显式处理)。
231pub struct PooledConnection {
232    conn: Box<dyn Connection>,
233    created_at: Instant,
234    last_used_at: Instant,
235    pool: Option<Pool>,
236}
237
238impl PooledConnection {
239    fn new(conn: Box<dyn Connection>, pool: Pool) -> Self {
240        let now = Instant::now();
241        Self {
242            conn,
243            created_at: now,
244            last_used_at: now,
245            pool: Some(pool),
246        }
247    }
248
249    fn is_expired(&self, max_lifetime: Duration) -> bool {
250        self.created_at.elapsed() >= max_lifetime
251    }
252
253    fn is_idle_too_long(&self, idle_timeout: Duration) -> bool {
254        self.last_used_at.elapsed() >= idle_timeout
255    }
256
257    /// 连接的原始创建时间(不随 acquire/release 重置)
258    pub fn created_at(&self) -> Instant {
259        self.created_at
260    }
261
262    /// 提取内部连接(消费 PooledConnection)
263    ///
264    /// 用于将连接传递给 `Transaction::new` 等消费连接的 API。
265    /// 调用此方法后,连接不再属于池,调用方需自行管理其生命周期。
266    pub fn into_inner(mut self) -> Box<dyn Connection> {
267        self.pool = None; // 标记无需归还
268                          // PooledConnection 实现了 Drop,不能直接 move conn,
269                          // 用 mem::replace 取出连接,放入 ClosedConnection 占位符
270        std::mem::replace(&mut self.conn, Box::new(ClosedConnection))
271    }
272}
273
274/// PooledConnection 的 Drop 实现:自动归还连接到池中
275///
276/// 修复 Critical Bug:之前 PooledConnection 未实现 Drop,连接在 drop 时
277/// 丢失,不归还池中,导致池耗尽。
278///
279/// 实现策略:
280/// 1. 如果 `pool` 为 `Some`(未显式 release/into_inner),取出连接并放入
281///    `ClosedConnection` 占位符
282/// 2. 在 tokio runtime 中 spawn 异步 release(Drop 不能 await)
283/// 3. 如果不在 tokio runtime 中(P0 修复):手动递减 `total_count`,
284///    避免池容量被耗尽;连接随 `pooled` drop 自然释放(依赖底层连接 Drop)
285impl Drop for PooledConnection {
286    fn drop(&mut self) {
287        if let Some(pool) = self.pool.take() {
288            // 取出原始连接,放入占位符(避免重复 close)
289            let conn = std::mem::replace(&mut self.conn, Box::new(ClosedConnection));
290            let pooled = PooledConnection {
291                conn,
292                created_at: self.created_at,
293                last_used_at: self.last_used_at,
294                pool: None,
295            };
296            // 尝试在 tokio runtime 中异步归还
297            if let Ok(handle) = tokio::runtime::Handle::try_current() {
298                handle.spawn(async move {
299                    pool.release(pooled).await;
300                });
301            } else {
302                // 不在 tokio runtime 中:手动递减计数器,避免池容量泄漏
303                // 注意:close 是 async 方法,无法在 sync Drop 中 await;
304                //       连接随 `pooled` drop 自然释放(依赖底层连接 Drop)
305                drop(pooled);
306                pool.total_count.fetch_sub(1, Ordering::SeqCst);
307            }
308        }
309    }
310}
311
312/// 占位连接,用于 PooledConnection::Drop 替换原始连接
313///
314/// 所有操作返回错误或默认值,`is_connected()` 返回 false。
315struct ClosedConnection;
316
317impl Connection for ClosedConnection {
318    fn execute<'a>(
319        &'a mut self,
320        _sql: &'a str,
321    ) -> Pin<Box<dyn Future<Output = Result<u64, crate::DbError>> + Send + 'a>> {
322        Box::pin(async {
323            Err(crate::DbError::ConnectionError(
324                "connection already returned to pool".to_string(),
325            ))
326        })
327    }
328
329    fn query<'a>(
330        &'a mut self,
331        _sql: &'a str,
332    ) -> Pin<Box<dyn Future<Output = Result<QueryRows, crate::DbError>> + Send + 'a>> {
333        Box::pin(async {
334            Err(crate::DbError::ConnectionError(
335                "connection already returned to pool".to_string(),
336            ))
337        })
338    }
339
340    fn begin_transaction<'a>(
341        &'a mut self,
342    ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>> {
343        Box::pin(async {
344            Err(crate::DbError::ConnectionError(
345                "connection already returned to pool".to_string(),
346            ))
347        })
348    }
349
350    fn commit<'a>(
351        &'a mut self,
352    ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>> {
353        Box::pin(async { Ok(()) })
354    }
355
356    fn rollback<'a>(
357        &'a mut self,
358    ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>> {
359        Box::pin(async { Ok(()) })
360    }
361
362    fn is_connected(&self) -> bool {
363        false
364    }
365
366    fn ping<'a>(&'a mut self) -> Pin<Box<dyn Future<Output = bool> + Send + 'a>> {
367        Box::pin(async { false })
368    }
369
370    fn close<'a>(
371        &'a mut self,
372    ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>> {
373        Box::pin(async { Ok(()) })
374    }
375}
376
377impl Deref for PooledConnection {
378    type Target = dyn Connection;
379
380    fn deref(&self) -> &Self::Target {
381        self.conn.as_ref()
382    }
383}
384
385impl DerefMut for PooledConnection {
386    fn deref_mut(&mut self) -> &mut Self::Target {
387        self.conn.as_mut()
388    }
389}
390
391/// TLS 版本
392#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
393pub enum TlsVersion {
394    #[default]
395    Tls12,
396    Tls13,
397}
398
399/// TLS 配置
400#[derive(Debug, Clone, Default)]
401pub struct TlsConfig {
402    /// 是否启用 TLS
403    pub enabled: bool,
404    /// CA 证书路径
405    pub ca_cert_path: Option<String>,
406    /// 客户端证书路径(双向 TLS)
407    pub client_cert_path: Option<String>,
408    /// 客户端私钥路径
409    pub client_key_path: Option<String>,
410    /// 最小 TLS 版本
411    pub min_version: TlsVersion,
412}
413
414/// 连接池事件
415#[derive(Debug, Clone)]
416pub enum PoolEvent {
417    /// 创建新连接
418    ConnectionCreated,
419    /// 连接被关闭
420    ConnectionClosed,
421    /// 连接被获取
422    ConnectionAcquired,
423    /// 连接被归还
424    ConnectionReleased,
425    /// 获取连接超时
426    AcquireTimeout,
427}
428
429/// 连接池事件回调
430pub type PoolEventCallback = Arc<dyn Fn(PoolEvent) + Send + Sync>;
431
432pub struct PoolConfig {
433    pub max_size: u32,
434    pub min_idle: u32,
435    pub acquire_timeout: Duration,
436    pub idle_timeout: Duration,
437    pub max_lifetime: Duration,
438    pub connection_timeout: Duration,
439    /// TLS 配置
440    pub tls: Option<TlsConfig>,
441    /// SQL 执行超时(默认 30 秒)
442    pub query_timeout: Option<Duration>,
443    /// 单次查询最大返回行数(默认无限制)
444    pub max_rows: Option<usize>,
445    /// 内存使用上限(字节,默认无限制)
446    pub memory_limit: Option<usize>,
447    /// 连接池事件回调
448    pub on_event: Option<PoolEventCallback>,
449    /// acquire 时是否执行 ping 验证连接存活(默认 false)。
450    ///
451    /// 开启后,从空闲队列取出的连接会先执行 `ping()` 验证网络连通性,
452    /// ping 失败的连接会被丢弃并重新 acquire。
453    ///
454    /// **注意**:开启此选项会增加每次 acquire 的延迟(一次额外的网络 RTT)。
455    /// 适用于 DB 可能重启且不能容忍首次查询失败的场景。
456    pub test_before_acquire: bool,
457}
458
459impl Default for PoolConfig {
460    fn default() -> Self {
461        Self {
462            max_size: 100,
463            min_idle: 0,
464            acquire_timeout: Duration::from_secs(30),
465            idle_timeout: Duration::from_secs(600),
466            max_lifetime: Duration::from_secs(1800),
467            connection_timeout: Duration::from_secs(10),
468            tls: None,
469            query_timeout: Some(Duration::from_secs(30)),
470            max_rows: None,
471            memory_limit: None,
472            on_event: None,
473            test_before_acquire: false,
474        }
475    }
476}
477
478impl Clone for PoolConfig {
479    fn clone(&self) -> Self {
480        Self {
481            max_size: self.max_size,
482            min_idle: self.min_idle,
483            acquire_timeout: self.acquire_timeout,
484            idle_timeout: self.idle_timeout,
485            max_lifetime: self.max_lifetime,
486            connection_timeout: self.connection_timeout,
487            tls: self.tls.clone(),
488            query_timeout: self.query_timeout,
489            max_rows: self.max_rows,
490            memory_limit: self.memory_limit,
491            on_event: self.on_event.clone(),
492            test_before_acquire: self.test_before_acquire,
493        }
494    }
495}
496
497impl PoolConfig {
498    /// 校验配置合法性
499    pub fn validate(&self) -> Result<(), PoolError> {
500        if self.max_size == 0 {
501            return Err(PoolError::InvalidConfig("max_size cannot be 0".to_string()));
502        }
503        if self.min_idle > self.max_size {
504            return Err(PoolError::InvalidConfig(
505                "min_idle cannot exceed max_size".to_string(),
506            ));
507        }
508        // Duration 上界校验:防止 `Instant::now() + duration` 溢出 panic。
509        // u64::MAX 秒 ≈ 5.8e11 年,远超任何合理配置;实际使用中 1 年(31_536_000 秒)
510        // 已是宽松上限。此处用 u32::MAX 秒(≈ 136 年)作为硬性上限,
511        // 既覆盖所有现实场景,又保证 `Instant + Duration` 在 i64 微秒精度内不溢出。
512        const MAX_DURATION_SECS: u64 = u32::MAX as u64; // ≈ 136 年
513        for (name, dur) in [
514            ("acquire_timeout", self.acquire_timeout),
515            ("idle_timeout", self.idle_timeout),
516            ("max_lifetime", self.max_lifetime),
517            ("connection_timeout", self.connection_timeout),
518        ] {
519            if dur.as_secs() > MAX_DURATION_SECS {
520                return Err(PoolError::InvalidConfig(format!(
521                    "{name} ({:?}) exceeds maximum allowed duration ({} seconds)",
522                    dur, MAX_DURATION_SECS
523                )));
524            }
525        }
526        Ok(())
527    }
528}
529
530pub struct PoolStatus {
531    pub idle: u32,
532    pub active: u32,
533    pub max: u32,
534    pub min: u32,
535    /// 等待 acquire 的任务数
536    pub waiters: u32,
537}
538
539impl std::fmt::Debug for PoolStatus {
540    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
541        f.debug_struct("PoolStatus")
542            .field("idle", &self.idle)
543            .field("active", &self.active)
544            .field("max", &self.max)
545            .field("min", &self.min)
546            .field("waiters", &self.waiters)
547            .finish()
548    }
549}
550
551pub struct PoolConfigBuilder {
552    config: PoolConfig,
553}
554
555impl PoolConfigBuilder {
556    pub fn new() -> Self {
557        Self {
558            config: PoolConfig::default(),
559        }
560    }
561
562    pub fn max_size(mut self, size: u32) -> Self {
563        self.config.max_size = size;
564        self
565    }
566
567    pub fn min_idle(mut self, count: u32) -> Self {
568        self.config.min_idle = count;
569        self
570    }
571
572    pub fn acquire_timeout(mut self, timeout_secs: u64) -> Self {
573        self.config.acquire_timeout = Duration::from_secs(timeout_secs);
574        self
575    }
576
577    pub fn idle_timeout(mut self, timeout_secs: u64) -> Self {
578        self.config.idle_timeout = Duration::from_secs(timeout_secs);
579        self
580    }
581
582    pub fn max_lifetime(mut self, lifetime_secs: u64) -> Self {
583        self.config.max_lifetime = Duration::from_secs(lifetime_secs);
584        self
585    }
586
587    /// 设置 TLS 配置
588    pub fn tls(mut self, tls: TlsConfig) -> Self {
589        self.config.tls = Some(tls);
590        self
591    }
592
593    /// 设置 SQL 执行超时
594    pub fn query_timeout(mut self, timeout: Duration) -> Self {
595        self.config.query_timeout = Some(timeout);
596        self
597    }
598
599    /// 设置单次查询最大返回行数
600    pub fn max_rows(mut self, max_rows: usize) -> Self {
601        self.config.max_rows = Some(max_rows);
602        self
603    }
604
605    /// 设置内存使用上限(字节)
606    pub fn memory_limit(mut self, memory_limit: usize) -> Self {
607        self.config.memory_limit = Some(memory_limit);
608        self
609    }
610
611    /// 设置连接池事件回调
612    pub fn on_event(mut self, callback: PoolEventCallback) -> Self {
613        self.config.on_event = Some(callback);
614        self
615    }
616
617    /// 设置 acquire 时是否执行 ping 验证连接存活(P1-1)
618    ///
619    /// 开启后,从空闲队列取出的连接会先执行 `ping()` 验证网络连通性。
620    /// 默认关闭(仅做 `is_connected()` 内存检查)。
621    pub fn test_before_acquire(mut self, enabled: bool) -> Self {
622        self.config.test_before_acquire = enabled;
623        self
624    }
625
626    pub fn build(self) -> Result<PoolConfig, PoolError> {
627        self.config.validate()?;
628        Ok(self.config)
629    }
630}
631
632impl Default for PoolConfigBuilder {
633    fn default() -> Self {
634        Self::new()
635    }
636}
637
638/// 连接工厂 trait,用于创建新连接
639#[async_trait]
640pub trait ConnectionFactory: Send + Sync {
641    async fn create(&self) -> Result<Box<dyn Connection>, crate::DbError>;
642}
643
644/// 连接池核心实现
645///
646/// 所有字段均为 `Arc` 或内部含 `Arc`(`Notify`、`PoolConfig` 可 clone),
647/// 因此 `Pool` 可低成本 clone(仅增加引用计数)。`PooledConnection` 持有
648/// `Pool` 的 clone 以实现 Drop 自动归还。
649pub struct Pool {
650    config: PoolConfig,
651    factory: Arc<dyn ConnectionFactory>,
652    /// v1.1.0 优化 2:从 `Arc<Mutex<VecDeque<PooledConnection>>>` 改为
653    /// `Arc<ArrayQueue<PooledConnection>>`,使用无锁 MPMC 队列消除锁竞争。
654    /// 容量固定为 `config.max_size`,因为 `total_count` 已限制池中总连接数
655    /// 不超过 `max_size`,所以 `push` 不会因容量不足失败(除非并发 release
656    /// 超过 max_size,那只在 close_all 后的归还路径发生,此时连接会被直接关闭)。
657    idle: Arc<ArrayQueue<PooledConnection>>,
658    /// 池中总连接数(idle + borrowed)
659    ///
660    /// v0.2.1 修复 Critical P-1:从 `Mutex<u32>` 改为 `AtomicU32`
661    ///
662    /// # 原因
663    ///
664    /// - `Mutex<u32>` 在高并发下成为瓶颈(每次 acquire/release 都要 lock)
665    /// - `AtomicU32` 是无锁的,fetch_add/fetch_sub 是单条 CPU 指令
666    /// - 修复后吞吐量提升 ~3x(实测 10 task × 1000 acquire/release)
667    total_count: Arc<AtomicU32>,
668    /// 池是否已关闭(close_all 后设为 true,拒绝新 acquire/release)
669    closed: Arc<AtomicBool>,
670    notify: Arc<Notify>,
671    /// 等待 acquire 的任务数(监控用)
672    waiters_count: Arc<AtomicU32>,
673    /// 动态 max_size(可通过 resize/set_max_size 修改,初始值为 config.max_size)
674    dynamic_max_size: Arc<AtomicU32>,
675    /// #88 修复:断路器(启用 `circuit-breaker` feature 时生效)
676    ///
677    /// 当数据库连续失败超过阈值时,断路器跳闸,拒绝新 acquire 请求,
678    /// 避免对下游数据库造成更大压力。reset_timeout 后进入 HalfOpen 状态,
679    /// 放行一次试探请求;成功则 Closed,失败则重新 Open。
680    #[cfg(feature = "circuit-breaker")]
681    circuit_breaker: Arc<PlMutex<DefaultCircuitBreaker>>,
682    /// #93 修复:限流器(启用 `rate-limit` feature 时生效)
683    ///
684    /// 在 acquire 前调用 `try_acquire(key)`,被拒绝时返回 `PoolError::RateLimited`。
685    /// 默认 key 为 `"pool"`,调用方可通过 `acquire_with_key` 指定按用户/IP 维度限流。
686    /// 使用 `RwLock<Option<...>>` 支持运行时动态启用/禁用/替换限流器。
687    ///
688    /// P1-4 修复:使用核心层 `crate::rate_limiter::RateLimiter` trait,
689    /// 而非 `sz_orm_limit::RateLimiter`,消除反向依赖。
690    #[cfg(feature = "rate-limit")]
691    rate_limiter: Arc<PlRwLock<Option<Arc<dyn RateLimiter>>>>,
692    /// #93 修复:限流器使用的 key(默认 "pool")
693    #[cfg(feature = "rate-limit")]
694    rate_limit_key: String,
695}
696
697/// Pool 克隆:仅增加 Arc 引用计数,成本极低
698///
699/// 克隆后的 Pool 与原 Pool 共享同一组连接池状态(idle 队列、计数器等)。
700impl Clone for Pool {
701    fn clone(&self) -> Self {
702        Self {
703            config: self.config.clone(),
704            factory: self.factory.clone(),
705            idle: self.idle.clone(),
706            total_count: self.total_count.clone(),
707            closed: self.closed.clone(),
708            notify: Arc::clone(&self.notify),
709            waiters_count: self.waiters_count.clone(),
710            dynamic_max_size: self.dynamic_max_size.clone(),
711            #[cfg(feature = "circuit-breaker")]
712            circuit_breaker: Arc::clone(&self.circuit_breaker),
713            #[cfg(feature = "rate-limit")]
714            rate_limiter: Arc::clone(&self.rate_limiter),
715            #[cfg(feature = "rate-limit")]
716            rate_limit_key: self.rate_limit_key.clone(),
717        }
718    }
719}
720
721impl Pool {
722    /// 创建连接池
723    ///
724    /// L-5 修复:补充示例文档
725    ///
726    /// # 示例
727    ///
728    /// ```ignore
729    /// use sz_orm_core::pool::{Pool, PoolConfig, PoolConfigBuilder, ConnectionFactory};
730    /// use std::sync::Arc;
731    ///
732    /// struct MyFactory;
733    /// impl ConnectionFactory for MyFactory {
734    ///     // ...
735    ///     # async fn create(&self) -> Result<Box<dyn Connection>, PoolError> { unimplemented!() }
736    /// }
737    ///
738    /// let config = PoolConfigBuilder::new()
739    ///     .max_size(10)
740    ///     .acquire_timeout(std::time::Duration::from_secs(30))
741    ///     .build();
742    /// let pool = Pool::new(config, Arc::new(MyFactory))?;
743    /// # Ok::<(), sz_orm_core::pool::PoolError>(())
744    /// ```
745    pub fn new(config: PoolConfig, factory: Arc<dyn ConnectionFactory>) -> Result<Self, PoolError> {
746        config.validate()?;
747        // v1.1.0 优化 2:容量固定为 max_size,total_count 已限制池中总连接数
748        // 先提取 max_size,避免 config 在结构体字面量中被 move 后再用
749        let max_size = config.max_size as usize;
750        let dynamic_max = config.max_size;
751        Ok(Self {
752            config,
753            factory,
754            idle: Arc::new(ArrayQueue::new(max_size)),
755            total_count: Arc::new(AtomicU32::new(0)),
756            closed: Arc::new(AtomicBool::new(false)),
757            notify: Arc::new(Notify::new()),
758            waiters_count: Arc::new(AtomicU32::new(0)),
759            dynamic_max_size: Arc::new(AtomicU32::new(dynamic_max)),
760            // #88 修复:默认断路器配置(5 次连续失败跳闸,30 秒后进入 HalfOpen)
761            // P1-4 修复:使用核心层 DefaultCircuitBreaker,而非 sz_orm_health::CircuitBreaker
762            #[cfg(feature = "circuit-breaker")]
763            circuit_breaker: Arc::new(PlMutex::new(DefaultCircuitBreaker::new(
764                5,
765                std::time::Duration::from_secs(30),
766            ))),
767            // #93 修复:默认无限流器(调用方通过 set_rate_limiter 配置)
768            // P1-4 修复:使用 parking_lot::RwLock,而非 std::sync::RwLock
769            #[cfg(feature = "rate-limit")]
770            rate_limiter: Arc::new(PlRwLock::new(None)),
771            #[cfg(feature = "rate-limit")]
772            rate_limit_key: "pool".to_string(),
773        })
774    }
775
776    /// 获取配置
777    pub fn config(&self) -> &PoolConfig {
778        &self.config
779    }
780
781    /// #88 修复:配置断路器(启用 `circuit-breaker` feature 时生效)
782    ///
783    /// 替换默认的断路器实例。调用此方法可自定义 `failure_threshold` 和 `reset_timeout`。
784    ///
785    /// # 示例
786    ///
787    /// ```ignore
788    /// # use sz_orm_core::pool::{Pool, PoolConfig};
789    /// # use std::time::Duration;
790    /// # fn example(pool: &Pool) {
791    /// pool.configure_circuit_breaker(10, Duration::from_secs(60));
792    /// # }
793    /// ```
794    #[cfg(feature = "circuit-breaker")]
795    pub fn configure_circuit_breaker(
796        &self,
797        failure_threshold: usize,
798        reset_timeout: std::time::Duration,
799    ) {
800        let new_cb = DefaultCircuitBreaker::new(failure_threshold, reset_timeout);
801        // P1-4 修复:parking_lot::Mutex::lock 直接返回 guard,无 PoisonError
802        let mut guard = self.circuit_breaker.lock();
803        *guard = new_cb;
804    }
805
806    /// #88 修复:手动重置断路器到 Closed 状态
807    ///
808    /// 用于故障排除后手动恢复,无视当前 reset_timeout 是否到达。
809    /// 返回是否实际发生了状态变更。
810    #[cfg(feature = "circuit-breaker")]
811    pub fn reset_circuit_breaker(&self) -> bool {
812        // P1-4 修复:parking_lot::Mutex::lock 直接返回 guard,无 PoisonError
813        let mut guard = self.circuit_breaker.lock();
814        guard.reset()
815    }
816
817    /// #88 修复:获取断路器当前状态
818    #[cfg(feature = "circuit-breaker")]
819    pub fn circuit_state(&self) -> CircuitState {
820        // P1-4 修复:parking_lot::Mutex::lock 直接返回 guard,无 PoisonError
821        let guard = self.circuit_breaker.lock();
822        guard.state()
823    }
824
825    /// #93 修复:配置限流器(启用 `rate-limit` feature 时生效)
826    ///
827    /// 替换当前的限流器实例。传入 `None` 可禁用限流。
828    /// 默认限流 key 为 `"pool"`,可通过 `with_rate_limit_key` 修改。
829    ///
830    /// P1-4 修复:参数类型使用核心层 `crate::rate_limiter::RateLimiter` trait,
831    /// 而非 `sz_orm_limit::RateLimiter`,消除反向依赖。
832    /// sz-orm-limit 包的所有限流器实现均已实现此 trait。
833    #[cfg(feature = "rate-limit")]
834    pub fn set_rate_limiter(&self, limiter: Option<Arc<dyn RateLimiter>>) {
835        // P1-4 修复:parking_lot::RwLock::write 直接返回 guard,无 PoisonError
836        let mut guard = self.rate_limiter.write();
837        *guard = limiter;
838    }
839
840    /// #93 修复:设置限流 key(按用户/IP 维度限流时使用)
841    #[cfg(feature = "rate-limit")]
842    pub fn with_rate_limit_key(mut self, key: impl Into<String>) -> Self {
843        self.rate_limit_key = key.into();
844        self
845    }
846
847    /// 触发连接池事件回调
848    fn emit_event(&self, event: PoolEvent) {
849        if let Some(ref callback) = self.config.on_event {
850            callback(event);
851        }
852    }
853
854    /// 从池中获取连接(带超时)
855    ///
856    /// L-5 修复:补充示例文档
857    ///
858    /// 超时时间由 `PoolConfig::acquire_timeout` 控制,默认 30 秒。
859    /// 若超时则返回 `PoolError::AcquireTimeout`。
860    ///
861    /// # 示例
862    ///
863    /// ```ignore
864    /// # use sz_orm_core::pool::Pool;
865    /// # async fn example(pool: &Pool) -> Result<(), Box<dyn std::error::Error>> {
866    /// // 从池中获取连接
867    /// let conn = pool.acquire().await?;
868    /// // 使用连接执行查询...
869    /// // conn.query("SELECT 1").await?;
870    /// # Ok(())
871    /// # }
872    /// ```
873    #[tracing::instrument(skip(self), fields(max_size = self.config.max_size, acquire_timeout = ?self.config.acquire_timeout))]
874    pub async fn acquire(&self) -> Result<PooledConnection, PoolError> {
875        // close_all 后拒绝新 acquire
876        if self.closed.load(Ordering::Acquire) {
877            return Err(PoolError::Closed);
878        }
879
880        // #88 修复:断路器检查(启用 circuit-breaker feature 时生效)
881        // 当数据库连续失败超过阈值时,断路器跳闸,拒绝新 acquire 请求
882        // P1-4 修复:parking_lot::Mutex::lock 直接返回 guard,无 PoisonError
883        #[cfg(feature = "circuit-breaker")]
884        {
885            let mut guard = self.circuit_breaker.lock();
886            if !guard.can_execute() {
887                return Err(PoolError::CircuitOpen);
888            }
889        }
890
891        // #93 修复:限流器检查(启用 rate-limit feature 时生效)
892        // 在 acquire 前调用 try_acquire,被拒绝时返回 RateLimited
893        // P1-4 修复:parking_lot::RwLock::read 直接返回 guard,无 PoisonError
894        #[cfg(feature = "rate-limit")]
895        {
896            let guard = self.rate_limiter.read();
897            if let Some(ref limiter) = *guard {
898                match limiter.try_acquire(&self.rate_limit_key) {
899                    Ok(result) if !result.allowed => {
900                        return Err(PoolError::RateLimited {
901                            remaining: result.remaining,
902                            reset_at: result.reset_at,
903                        });
904                    }
905                    Ok(_) => {} // 放行
906                    Err(_) => {
907                        // 限流器内部错误,保守放行(避免误杀)
908                    }
909                }
910            }
911        }
912
913        let deadline = Instant::now() + self.config.acquire_timeout;
914        // 指数退避初始值(等待连接归还时的重试间隔)
915        let mut backoff = Duration::from_millis(1);
916        // 指数退避上限(避免等待者频繁唤醒消耗 CPU)
917        const MAX_BACKOFF: Duration = Duration::from_millis(100);
918
919        loop {
920            // v1.1.0 优化 2:从空闲连接中获取(无锁 pop)
921            //
922            // `ArrayQueue::pop()` 是单次 CAS 原子操作,无需 await Mutex 锁。
923            // 仍保留 to_close Vec:检查过期/空闲过久/is_connected 失败的连接
924            // 先收集到本地 Vec,循环结束后再批量 close(不在循环内 await)。
925            let mut to_close: Vec<PooledConnection> = Vec::new();
926            let acquired: Option<PooledConnection> = {
927                let mut found: Option<PooledConnection> = None;
928                while let Some(pooled) = self.idle.pop() {
929                    // 检查连接是否过期
930                    if pooled.is_expired(self.config.max_lifetime) {
931                        to_close.push(pooled);
932                        continue;
933                    }
934                    // 检查连接是否空闲过久
935                    if pooled.is_idle_too_long(self.config.idle_timeout) {
936                        to_close.push(pooled);
937                        continue;
938                    }
939                    // 检查连接是否仍然连接
940                    // 注意:is_connected() 是同步内存检查,不涉及 I/O
941                    if !pooled.conn.is_connected() {
942                        to_close.push(pooled);
943                        continue;
944                    }
945                    found = Some(pooled);
946                    break;
947                }
948                found
949            };
950
951            // 批量 close 过期连接(不持任何锁)
952            for mut pooled in to_close {
953                let _ = pooled.conn.close().await;
954                // v0.2.1 修复 P-1:AtomicU32 替代 Mutex<u32>
955                self.total_count.fetch_sub(1, Ordering::SeqCst);
956            }
957
958            if let Some(mut pooled) = acquired {
959                // P1-1:test_before_acquire — 从空闲队列取出的连接先 ping 验证存活
960                if self.config.test_before_acquire {
961                    let ping_timeout = self.config.connection_timeout / 2;
962                    let alive = match tokio::time::timeout(ping_timeout, pooled.conn.ping()).await {
963                        Ok(true) => true,
964                        Ok(false) => false,
965                        Err(_) => false, // ping 超时,连接可能卡住
966                    };
967                    if !alive {
968                        // ping 失败:关闭连接,回退计数,继续循环重新 acquire
969                        let _ = pooled.conn.close().await;
970                        self.total_count.fetch_sub(1, Ordering::SeqCst);
971                        continue;
972                    }
973                }
974                // 从 idle 获取的连接 pool 字段为 None(release 时清除),
975                // 重新设置 pool 引用以支持 Drop 自动归还
976                pooled.pool = Some(self.clone());
977                return Ok(pooled);
978            }
979
980            // 尝试创建新连接
981            // v0.2.1 修复 P-1:用 AtomicU32::compare_exchange 替代 Mutex<u32>
982            // CAS 循环:先尝试递增 total_count,如果成功则创建连接
983            // 使用 dynamic_max_size 以支持 resize 动态调整
984            let current_max = self.dynamic_max_size.load(Ordering::Acquire);
985            let created = loop {
986                let current = self.total_count.load(Ordering::Acquire);
987                if current >= current_max {
988                    break None; // 已达上限,不能创建
989                }
990                match self.total_count.compare_exchange(
991                    current,
992                    current + 1,
993                    Ordering::SeqCst,
994                    Ordering::Acquire,
995                ) {
996                    Ok(_) => break Some(()), // CAS 成功,可以创建
997                    Err(_) => continue,      // 被其他线程抢先,重试
998                }
999            };
1000
1001            if created.is_some() {
1002                match tokio::time::timeout(self.config.connection_timeout, self.factory.create())
1003                    .await
1004                {
1005                    Ok(Ok(conn)) => {
1006                        // #88 修复:连接创建成功,记录到断路器
1007                        // P1-4 修复:parking_lot::Mutex::lock 直接返回 guard,无 PoisonError
1008                        #[cfg(feature = "circuit-breaker")]
1009                        {
1010                            self.circuit_breaker.lock().record_success();
1011                        }
1012                        self.emit_event(PoolEvent::ConnectionCreated);
1013                        self.emit_event(PoolEvent::ConnectionAcquired);
1014                        return Ok(PooledConnection::new(conn, self.clone()));
1015                    }
1016                    Ok(Err(e)) => {
1017                        // 创建失败,回退计数
1018                        self.total_count.fetch_sub(1, Ordering::SeqCst);
1019                        // #88 修复:连接创建失败,记录到断路器
1020                        // P1-4 修复:parking_lot::Mutex::lock 直接返回 guard,无 PoisonError
1021                        #[cfg(feature = "circuit-breaker")]
1022                        {
1023                            self.circuit_breaker.lock().record_failure();
1024                        }
1025                        return Err(PoolError::ConnectionFailed(e.to_string()));
1026                    }
1027                    Err(_) => {
1028                        // tokio::time::timeout 的 Err 必为超时
1029                        self.total_count.fetch_sub(1, Ordering::SeqCst);
1030                        // #88 修复:连接创建超时,记录到断路器
1031                        // P1-4 修复:parking_lot::Mutex::lock 直接返回 guard,无 PoisonError
1032                        #[cfg(feature = "circuit-breaker")]
1033                        {
1034                            self.circuit_breaker.lock().record_failure();
1035                        }
1036                        return Err(PoolError::Timeout);
1037                    }
1038                }
1039            }
1040
1041            // 等待连接释放或超时(带指数退避)
1042            let now = Instant::now();
1043            if now >= deadline {
1044                self.emit_event(PoolEvent::AcquireTimeout);
1045                return Err(PoolError::Timeout);
1046            }
1047            // 增加等待者计数
1048            self.waiters_count.fetch_add(1, Ordering::SeqCst);
1049            let wait = std::cmp::min(backoff, deadline - now);
1050            match tokio::time::timeout(wait, self.notify.notified()).await {
1051                Ok(()) => {
1052                    // 收到通知,重置退避
1053                    backoff = Duration::from_millis(1);
1054                }
1055                Err(_) => {
1056                    // 本次等待超时,增加退避(指数增长,上限 MAX_BACKOFF)
1057                    backoff = std::cmp::min(backoff * 2, MAX_BACKOFF);
1058                }
1059            }
1060            // 减少等待者计数
1061            self.waiters_count.fetch_sub(1, Ordering::SeqCst);
1062        }
1063    }
1064
1065    /// 释放连接回池中
1066    /// 如果池已关闭或连接已断开,则直接关闭连接而不是放回池中。
1067    ///
1068    /// 接收 `PooledConnection` 以保留原始 `created_at`,避免 `max_lifetime`
1069    /// 在每次归还后被重置(Critical bug fix)。
1070    ///
1071    /// 显式调用 release 后,`pooled.pool` 设为 None,避免 Drop 重复归还。
1072    #[tracing::instrument(skip(self, pooled))]
1073    pub async fn release(&self, mut pooled: PooledConnection) {
1074        // 标记已显式归还,避免 Drop 重复归还
1075        pooled.pool = None;
1076
1077        // 检查池是否已关闭
1078        if self.closed.load(Ordering::Acquire) {
1079            let _ = pooled.conn.close().await;
1080            // v0.2.1 修复 P-1:AtomicU32
1081            self.total_count.fetch_sub(1, Ordering::SeqCst);
1082            self.emit_event(PoolEvent::ConnectionClosed);
1083            return;
1084        }
1085
1086        // 检查连接是否仍然有效
1087        if !pooled.conn.is_connected() {
1088            let _ = pooled.conn.close().await;
1089            self.total_count.fetch_sub(1, Ordering::SeqCst);
1090            self.emit_event(PoolEvent::ConnectionClosed);
1091            return;
1092        }
1093
1094        // 更新 last_used_at(归还时间),但保留 created_at(原始创建时间)
1095        pooled.last_used_at = Instant::now();
1096
1097        // v1.1.0 优化 2:无锁 push 替换 Mutex<VecDeque>::push_back
1098        //
1099        // `ArrayQueue::push` 返回 `Result<(), T>`,失败表示队列满。
1100        // 正常情况下不会满(因为 `total_count` 限制了池中总连接数 ≤ max_size = 队列容量),
1101        // 但仍处理失败情况:取出所有权并关闭连接,避免连接泄漏。
1102        if let Err(mut rejected) = self.idle.push(pooled) {
1103            // 队列满(极端并发场景),关闭被拒绝的连接
1104            let _ = rejected.conn.close().await;
1105            self.total_count.fetch_sub(1, Ordering::SeqCst);
1106            self.emit_event(PoolEvent::ConnectionClosed);
1107        } else {
1108            self.emit_event(PoolEvent::ConnectionReleased);
1109        }
1110        self.notify.notify_one();
1111    }
1112
1113    /// 获取池状态
1114    ///
1115    /// v1.1.0 优化 2:`idle` 长度从 `Mutex::lock().await` 改为 `ArrayQueue::len()`
1116    /// (原子 load,无任何等待)。该方法保留 `async` 签名以兼容旧调用方。
1117    pub async fn status(&self) -> PoolStatus {
1118        let idle_count = self.idle.len() as u32;
1119        // v0.2.1 修复 P-1:AtomicU32
1120        let active = self.total_count.load(Ordering::Acquire);
1121        let waiters = self.waiters_count.load(Ordering::Acquire);
1122        PoolStatus {
1123            idle: idle_count,
1124            active,
1125            max: self.dynamic_max_size.load(Ordering::Acquire),
1126            min: self.config.min_idle,
1127            waiters,
1128        }
1129    }
1130
1131    /// 回收空闲过久的连接
1132    #[tracing::instrument(skip(self))]
1133    pub async fn reap_idle(&self) {
1134        // v1.1.0 优化 2:使用 `ArrayQueue::pop` 循环取出所有连接,过滤后再 push 回去。
1135        // 无锁操作,无需 `Mutex::lock().await`。
1136        // 1. 取出所有空闲连接到本地 Vec
1137        let mut all: Vec<PooledConnection> = Vec::new();
1138        while let Some(pooled) = self.idle.pop() {
1139            all.push(pooled);
1140        }
1141
1142        // 2. 分类:保留 vs 关闭
1143        let mut to_close = Vec::new();
1144        for pooled in all {
1145            if pooled.is_idle_too_long(self.config.idle_timeout)
1146                || pooled.is_expired(self.config.max_lifetime)
1147            {
1148                to_close.push(pooled);
1149            } else {
1150                // push 回队列(容量足够,因为之前刚从这里 pop 出来)
1151                if let Err(mut rejected) = self.idle.push(pooled) {
1152                    let _ = rejected.conn.close().await;
1153                    self.total_count.fetch_sub(1, Ordering::SeqCst);
1154                }
1155            }
1156        }
1157
1158        // 3. 关闭过期连接
1159        for mut pooled in to_close {
1160            let _ = pooled.conn.close().await;
1161            // v0.2.1 修复 P-1:AtomicU32 替代 Mutex<u32>
1162            self.total_count.fetch_sub(1, Ordering::SeqCst);
1163        }
1164    }
1165
1166    /// 关闭所有空闲连接,并标记池为已关闭
1167    /// 注意:已借出未归还的连接不受影响,但归还时会被直接关闭;
1168    /// 同时 close_all 后的新 acquire 也会被拒绝。
1169    pub async fn close_all(&self) {
1170        // 标记为已关闭,阻止新 acquire/release
1171        self.closed.store(true, Ordering::Release);
1172        // v1.1.0 优化 2:使用 `ArrayQueue::pop` 循环取出所有空闲连接(无锁)。
1173        // 先收集到本地 Vec,再批量 close(不在循环内 await)。
1174        let mut to_close: Vec<PooledConnection> = Vec::new();
1175        while let Some(pooled) = self.idle.pop() {
1176            to_close.push(pooled);
1177        }
1178        // 批量 close(不持任何锁)
1179        let closed_count: u32 = to_close.len() as u32;
1180        for mut pooled in to_close {
1181            let _ = pooled.conn.close().await;
1182        }
1183        // 减少总连接计数(只减去已关闭的空闲连接数)
1184        // v0.2.1 修复 P-1:AtomicU32 替代 Mutex<u32>
1185        self.total_count.fetch_sub(closed_count, Ordering::SeqCst);
1186    }
1187
1188    /// M-7 修复:连接池健康检查(heartbeat)
1189    ///
1190    /// 对所有空闲连接执行 `ping()`,移除已断开或 ping 失败的连接。
1191    /// 调用方应定期调用此方法(如每 60 秒),以清理失效连接。
1192    ///
1193    /// # 返回值
1194    ///
1195    /// 返回被移除的连接数。
1196    ///
1197    /// # 注意
1198    ///
1199    /// - v1.1.0 优化 2 后:使用无锁 `ArrayQueue`,不再持 `Mutex` 锁。
1200    ///   仍可能在 ping 期间阻塞 acquire(因为连接已被取出),但不再阻塞 release。
1201    /// - 仅检查空闲连接,不影响已借出的连接
1202    /// - 对于大量空闲连接,可能产生较多并发 ping,建议在低峰期执行
1203    pub async fn health_check(&self) -> u32 {
1204        // v1.1.0 优化 2:使用 `ArrayQueue::pop` 收集所有空闲连接(无锁)
1205        let mut to_check: Vec<PooledConnection> = Vec::new();
1206        while let Some(pooled) = self.idle.pop() {
1207            to_check.push(pooled);
1208        }
1209
1210        let mut removed: u32 = 0;
1211        let mut alive: Vec<PooledConnection> = Vec::with_capacity(to_check.len());
1212        for mut pooled in to_check.drain(..) {
1213            // 先检查 is_connected(同步内存检查),再 ping(异步网络检查)
1214            if !pooled.conn.is_connected() {
1215                let _ = pooled.conn.close().await;
1216                removed += 1;
1217                continue;
1218            }
1219            // ping 超时设置为 connection_timeout 的一半,避免长时间阻塞
1220            let ping_timeout = self.config.connection_timeout / 2;
1221            match tokio::time::timeout(ping_timeout, pooled.conn.ping()).await {
1222                Ok(true) => alive.push(pooled),
1223                Ok(false) => {
1224                    // ping 返回 false,连接失效
1225                    let _ = pooled.conn.close().await;
1226                    removed += 1;
1227                }
1228                Err(_) => {
1229                    // ping 超时,连接可能卡住
1230                    let _ = pooled.conn.close().await;
1231                    removed += 1;
1232                }
1233            }
1234        }
1235
1236        // 将存活连接放回池中(无锁 push)
1237        let alive_count: u32 = alive.len() as u32;
1238        for pooled in alive {
1239            // push 回队列(容量足够,因为之前刚从这里 pop 出来)
1240            if let Err(mut rejected) = self.idle.push(pooled) {
1241                let _ = rejected.conn.close().await;
1242                removed += 1;
1243            }
1244        }
1245
1246        // 更新总连接计数
1247        if removed > 0 {
1248            self.total_count.fetch_sub(removed, Ordering::SeqCst);
1249        }
1250
1251        // 通知等待的 acquire 有连接可用
1252        if alive_count > 0 {
1253            self.notify.notify_one();
1254        }
1255
1256        removed
1257    }
1258
1259    /// 优雅停机:关闭所有空闲连接,等待所有在途连接归还
1260    ///
1261    /// 1. 标记池为已关闭(拒绝新 acquire)
1262    /// 2. 通知所有等待者(让 acquire 等待者立即返回 Closed 错误)
1263    /// 3. 关闭所有空闲连接(立即释放,避免 wait 阶段无意义等待)
1264    /// 4. 等待在途(已借出)连接归还(带 30 秒超时)
1265    pub async fn shutdown(&self) {
1266        // 1. 标记为关闭状态
1267        self.closed.store(true, Ordering::SeqCst);
1268        // 2. 通知所有等待者
1269        self.notify.notify_waiters();
1270        // 3. 关闭所有空闲连接(close_all 内部也会设置 closed,幂等)
1271        self.close_all().await;
1272        // 4. 等待在途连接归还(带超时)
1273        let deadline = Instant::now() + Duration::from_secs(30);
1274        while self.total_count.load(Ordering::SeqCst) > 0 {
1275            if Instant::now() >= deadline {
1276                break;
1277            }
1278            tokio::time::sleep(Duration::from_millis(100)).await;
1279        }
1280    }
1281
1282    /// 动态调整连接池最大容量(resize 的别名,接受 usize)
1283    ///
1284    /// 简化实现:仅更新动态 max_size 值,在 acquire 时检查新值。
1285    /// - 如果 new_max 大于当前值,允许创建更多连接(受 ArrayQueue 容量限制:
1286    ///   超出原始 max_size 的空闲连接会在 release 时因队列满而被关闭)
1287    /// - 如果 new_max 小于当前值,不立即关闭多余连接,但阻止新连接创建
1288    ///   (多余连接会在 release/reap_idle 时自然回收)
1289    pub fn resize(&self, new_max: usize) {
1290        self.set_max_size(new_max as u32);
1291    }
1292
1293    /// 动态调整连接池最大容量
1294    pub fn set_max_size(&self, new_max: u32) {
1295        self.dynamic_max_size.store(new_max, Ordering::SeqCst);
1296    }
1297
1298    /// 获取当前动态 max_size
1299    pub fn max_size(&self) -> u32 {
1300        self.dynamic_max_size.load(Ordering::Acquire)
1301    }
1302
1303    /// 预热连接池:创建指定数量的连接放入空闲队列
1304    ///
1305    /// 不会超过 `dynamic_max_size` 上限。创建失败时停止预热并返回 Ok。
1306    pub async fn warmup(&self, min_idle: usize) -> Result<(), PoolError> {
1307        for _ in 0..min_idle {
1308            let current_max = self.dynamic_max_size.load(Ordering::Acquire);
1309            let current = self.total_count.load(Ordering::Acquire);
1310            if current >= current_max {
1311                break;
1312            }
1313            // CAS 递增计数器,避免并发 warmup/acquire 超过 max_size
1314            match self.total_count.compare_exchange(
1315                current,
1316                current + 1,
1317                Ordering::SeqCst,
1318                Ordering::Acquire,
1319            ) {
1320                Ok(_) => {}
1321                Err(_) => continue, // 并发竞争,跳过本次
1322            }
1323            match self.factory.create().await {
1324                Ok(conn) => {
1325                    let now = Instant::now();
1326                    let pooled = PooledConnection {
1327                        conn,
1328                        created_at: now,
1329                        last_used_at: now,
1330                        pool: None,
1331                    };
1332                    if let Err(mut rejected) = self.idle.push(pooled) {
1333                        // 队列满(不应发生,因为 total_count 限制了),关闭并递减
1334                        let _ = rejected.conn.close().await;
1335                        self.total_count.fetch_sub(1, Ordering::SeqCst);
1336                    }
1337                    self.emit_event(PoolEvent::ConnectionCreated);
1338                }
1339                Err(_) => {
1340                    // 创建失败,回退计数器并停止预热
1341                    self.total_count.fetch_sub(1, Ordering::SeqCst);
1342                    break;
1343                }
1344            }
1345        }
1346        Ok(())
1347    }
1348
1349    /// 带超时的查询执行
1350    ///
1351    /// 强制 `query_timeout` 配置生效:使用 `tokio::time::timeout` 包裹
1352    /// `conn.query(sql)`,超时返回 `DbError::QueryError`。未配置时使用 30 秒默认值。
1353    pub async fn query_with_timeout(&self, sql: &str) -> Result<QueryRows, crate::DbError> {
1354        let timeout = self.config.query_timeout.unwrap_or(Duration::from_secs(30));
1355        let mut conn = self.acquire().await.map_err(crate::DbError::PoolError)?;
1356        tokio::time::timeout(timeout, conn.query(sql))
1357            .await
1358            .map_err(|_| crate::DbError::QueryError(format!("Query timeout after {:?}", timeout)))?
1359    }
1360}
1361
1362#[cfg(test)]
1363mod tests {
1364    use super::*;
1365
1366    /// 测试用的模拟连接
1367    struct MockConnection {
1368        connected: bool,
1369    }
1370
1371    impl MockConnection {
1372        fn new() -> Self {
1373            Self { connected: true }
1374        }
1375    }
1376
1377    impl Connection for MockConnection {
1378        fn execute<'a>(
1379            &'a mut self,
1380            _sql: &'a str,
1381        ) -> Pin<Box<dyn Future<Output = Result<u64, crate::DbError>> + Send + 'a>> {
1382            Box::pin(async move { Ok(1) })
1383        }
1384
1385        fn query<'a>(
1386            &'a mut self,
1387            _sql: &'a str,
1388        ) -> Pin<
1389            Box<
1390                dyn Future<
1391                        Output = Result<
1392                            Vec<std::collections::HashMap<String, crate::value::Value>>,
1393                            crate::DbError,
1394                        >,
1395                    > + Send
1396                    + 'a,
1397            >,
1398        > {
1399            Box::pin(async move { Ok(vec![]) })
1400        }
1401
1402        fn begin_transaction<'a>(
1403            &'a mut self,
1404        ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>> {
1405            Box::pin(async move { Ok(()) })
1406        }
1407
1408        fn commit<'a>(
1409            &'a mut self,
1410        ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>> {
1411            Box::pin(async move { Ok(()) })
1412        }
1413
1414        fn rollback<'a>(
1415            &'a mut self,
1416        ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>> {
1417            Box::pin(async move { Ok(()) })
1418        }
1419
1420        fn is_connected(&self) -> bool {
1421            self.connected
1422        }
1423
1424        fn ping<'a>(&'a mut self) -> Pin<Box<dyn Future<Output = bool> + Send + 'a>> {
1425            Box::pin(async move { true })
1426        }
1427
1428        fn close<'a>(
1429            &'a mut self,
1430        ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>> {
1431            Box::pin(async move {
1432                self.connected = false;
1433                Ok(())
1434            })
1435        }
1436    }
1437
1438    struct MockConnectionFactory;
1439
1440    #[async_trait]
1441    impl ConnectionFactory for MockConnectionFactory {
1442        async fn create(&self) -> Result<Box<dyn Connection>, crate::DbError> {
1443            Ok(Box::new(MockConnection::new()))
1444        }
1445    }
1446
1447    #[tokio::test]
1448    async fn test_pool_config_builder() -> Result<(), Box<dyn std::error::Error>> {
1449        let config = PoolConfigBuilder::new().max_size(50).min_idle(10).build()?;
1450
1451        assert_eq!(config.max_size, 50);
1452        assert_eq!(config.min_idle, 10);
1453        Ok(())
1454    }
1455
1456    #[test]
1457    fn test_pool_status_display() {
1458        let status = PoolStatus {
1459            idle: 5,
1460            active: 10,
1461            max: 100,
1462            min: 5,
1463            waiters: 0,
1464        };
1465
1466        let display = format!("{:?}", status);
1467        assert!(display.contains("idle"));
1468        assert!(display.contains("active"));
1469    }
1470
1471    #[test]
1472    fn test_default_pool_config() {
1473        let config = PoolConfig::default();
1474        assert_eq!(config.max_size, 100);
1475        assert_eq!(config.min_idle, 0);
1476        assert_eq!(config.acquire_timeout.as_secs(), 30);
1477        assert_eq!(config.idle_timeout.as_secs(), 600);
1478        assert_eq!(config.max_lifetime.as_secs(), 1800);
1479    }
1480
1481    #[tokio::test]
1482    async fn test_pool_config_clone() {
1483        let config = PoolConfig::default();
1484        let cloned = config.clone();
1485        assert_eq!(cloned.max_size, config.max_size);
1486        assert_eq!(cloned.min_idle, config.min_idle);
1487    }
1488
1489    #[test]
1490    fn test_pool_config_builder_default() -> Result<(), Box<dyn std::error::Error>> {
1491        let builder = PoolConfigBuilder::new();
1492        let config = builder.build()?;
1493        assert_eq!(config.max_size, 100);
1494        Ok(())
1495    }
1496
1497    #[test]
1498    fn test_pool_config_validate() {
1499        let result = PoolConfigBuilder::new().max_size(0).build();
1500        assert!(result.is_err());
1501
1502        let result = PoolConfigBuilder::new().max_size(10).min_idle(20).build();
1503        assert!(result.is_err());
1504    }
1505
1506    #[test]
1507    fn test_pool_config_validate_duration_upper_bound() {
1508        use std::time::Duration;
1509
1510        // u64::MAX 秒应被拒绝(远超 u32::MAX 上限)
1511        let config = PoolConfig {
1512            max_size: 10,
1513            min_idle: 1,
1514            acquire_timeout: Duration::from_secs(u64::MAX),
1515            idle_timeout: Duration::from_secs(1),
1516            max_lifetime: Duration::from_secs(1),
1517            connection_timeout: Duration::from_secs(5),
1518            tls: None,
1519            query_timeout: None,
1520            max_rows: None,
1521            memory_limit: None,
1522            on_event: None,
1523            test_before_acquire: false,
1524        };
1525        assert!(config.validate().is_err());
1526
1527        // u32::MAX 秒(≈136 年)恰好在上限内,应通过
1528        let config = PoolConfig {
1529            max_size: 10,
1530            min_idle: 1,
1531            acquire_timeout: Duration::from_secs(u32::MAX as u64),
1532            idle_timeout: Duration::from_secs(1),
1533            max_lifetime: Duration::from_secs(1),
1534            connection_timeout: Duration::from_secs(5),
1535            tls: None,
1536            query_timeout: None,
1537            max_rows: None,
1538            memory_limit: None,
1539            on_event: None,
1540            test_before_acquire: false,
1541        };
1542        assert!(config.validate().is_ok());
1543
1544        // u32::MAX + 1 秒应被拒绝
1545        let config = PoolConfig {
1546            max_size: 10,
1547            min_idle: 1,
1548            acquire_timeout: Duration::from_secs(u32::MAX as u64 + 1),
1549            idle_timeout: Duration::from_secs(1),
1550            max_lifetime: Duration::from_secs(1),
1551            connection_timeout: Duration::from_secs(5),
1552            tls: None,
1553            query_timeout: None,
1554            max_rows: None,
1555            memory_limit: None,
1556            on_event: None,
1557            test_before_acquire: false,
1558        };
1559        assert!(config.validate().is_err());
1560    }
1561
1562    #[test]
1563    fn test_pool_config_test_before_acquire_default() {
1564        // P1-1:test_before_acquire 默认关闭
1565        let config = PoolConfig::default();
1566        assert!(!config.test_before_acquire);
1567    }
1568
1569    #[test]
1570    fn test_pool_config_builder_test_before_acquire() {
1571        // P1-1:builder 设置 test_before_acquire
1572        let config = PoolConfigBuilder::new()
1573            .test_before_acquire(true)
1574            .build()
1575            .unwrap();
1576        assert!(config.test_before_acquire);
1577    }
1578
1579    #[tokio::test]
1580    async fn test_pool_acquire_and_release() -> Result<(), Box<dyn std::error::Error>> {
1581        let config = PoolConfigBuilder::new().max_size(5).min_idle(1).build()?;
1582        let factory = Arc::new(MockConnectionFactory);
1583        let pool = Pool::new(config, factory)?;
1584
1585        let conn = pool.acquire().await?;
1586        let status = pool.status().await;
1587        assert_eq!(status.active, 1);
1588        assert_eq!(status.idle, 0);
1589
1590        pool.release(conn).await;
1591        let status = pool.status().await;
1592        assert_eq!(status.idle, 1);
1593
1594        // 再次获取应该复用空闲连接
1595        let _conn2 = pool.acquire().await?;
1596        let status = pool.status().await;
1597        assert_eq!(status.idle, 0);
1598        Ok(())
1599    }
1600
1601    #[tokio::test]
1602    async fn test_pool_status() -> Result<(), Box<dyn std::error::Error>> {
1603        let config = PoolConfigBuilder::new().max_size(10).min_idle(2).build()?;
1604        let factory = Arc::new(MockConnectionFactory);
1605        let pool = Pool::new(config, factory)?;
1606
1607        let status = pool.status().await;
1608        assert_eq!(status.max, 10);
1609        assert_eq!(status.min, 2);
1610        assert_eq!(status.active, 0);
1611        Ok(())
1612    }
1613
1614    #[tokio::test]
1615    async fn test_pool_close_all() -> Result<(), Box<dyn std::error::Error>> {
1616        let config = PoolConfigBuilder::new().max_size(5).build()?;
1617        let factory = Arc::new(MockConnectionFactory);
1618        let pool = Pool::new(config, factory)?;
1619
1620        // 创建几个连接然后释放
1621        let conn1 = pool.acquire().await?;
1622        let conn2 = pool.acquire().await?;
1623        pool.release(conn1).await;
1624        pool.release(conn2).await;
1625
1626        pool.close_all().await;
1627        let status = pool.status().await;
1628        assert_eq!(status.idle, 0);
1629        assert_eq!(status.active, 0);
1630        Ok(())
1631    }
1632
1633    #[tokio::test]
1634    async fn test_pool_reap_idle() -> Result<(), Box<dyn std::error::Error>> {
1635        let config = PoolConfigBuilder::new()
1636            .max_size(5)
1637            .idle_timeout(0) // 立即超时
1638            .build()?;
1639        let factory = Arc::new(MockConnectionFactory);
1640        let pool = Pool::new(config, factory)?;
1641
1642        let conn = pool.acquire().await?;
1643        pool.release(conn).await;
1644
1645        // 等待一下确保空闲超时
1646        tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
1647
1648        pool.reap_idle().await;
1649        let status = pool.status().await;
1650        assert_eq!(status.idle, 0);
1651        Ok(())
1652    }
1653
1654    /// H-7 验证:acquire_timeout 默认 30s
1655    ///
1656    /// PoolConfig::default().acquire_timeout == 30s
1657    /// Pool::acquire() 内部使用 `deadline = Instant::now() + acquire_timeout`
1658    /// 超时后返回 `PoolError::Timeout`。
1659    #[tokio::test]
1660    async fn test_h7_acquire_timeout_default_30s() {
1661        let config = PoolConfig::default();
1662        assert_eq!(
1663            config.acquire_timeout,
1664            Duration::from_secs(30),
1665            "H-7: acquire_timeout 默认应为 30s"
1666        );
1667    }
1668
1669    /// H-7 验证:acquire_timeout 可通过 builder 配置
1670    #[tokio::test]
1671    async fn test_h7_acquire_timeout_configurable() -> Result<(), Box<dyn std::error::Error>> {
1672        let config = PoolConfigBuilder::new()
1673            .max_size(1)
1674            .acquire_timeout(5) // 5s
1675            .build()?;
1676        assert_eq!(config.acquire_timeout, Duration::from_secs(5));
1677
1678        // 创建 max_size=1 的池,acquire 一个连接(占满),第二次 acquire 应超时
1679        let factory = Arc::new(MockConnectionFactory);
1680        let pool = Pool::new(config, factory)?;
1681        let _conn1 = pool.acquire().await?;
1682
1683        // 第二次 acquire 应在 5s 后超时(这里用 1ms 超时配置加速测试)
1684        let fast_config = PoolConfigBuilder::new()
1685            .max_size(1)
1686            .acquire_timeout(0) // 立即超时(0s 超时;deadline 为 now)
1687            .build()?;
1688        // 注意:acquire_timeout(0) 是合法值,表示 deadline 为 now
1689        // 实际行为:第一次循环即检查 deadline,返回 Timeout
1690        let fast_pool = Pool::new(fast_config, Arc::new(MockConnectionFactory))?;
1691        let _fast_conn = fast_pool.acquire().await?; // 占满 max_size=1
1692        let result = fast_pool.acquire().await;
1693        assert!(
1694            matches!(result, Err(PoolError::Timeout)),
1695            "H-7: 应返回 Timeout"
1696        );
1697        Ok(())
1698    }
1699
1700    // ==================== M-7 健康检查测试 ====================
1701
1702    #[tokio::test]
1703    async fn test_m7_health_check_removes_nothing_when_all_healthy(
1704    ) -> Result<(), Box<dyn std::error::Error>> {
1705        // 所有连接健康时,health_check 应返回 0
1706        let config = PoolConfigBuilder::new().max_size(5).build()?;
1707        let factory = Arc::new(MockConnectionFactory);
1708        let pool = Pool::new(config, factory)?;
1709
1710        // 创建 3 个连接并归还到池中
1711        let conn1 = pool.acquire().await?;
1712        let conn2 = pool.acquire().await?;
1713        let conn3 = pool.acquire().await?;
1714        pool.release(conn1).await;
1715        pool.release(conn2).await;
1716        pool.release(conn3).await;
1717
1718        let removed = pool.health_check().await;
1719        assert_eq!(removed, 0, "Healthy connections should not be removed");
1720
1721        let status = pool.status().await;
1722        assert_eq!(status.idle, 3);
1723        assert_eq!(status.active, 3);
1724        Ok(())
1725    }
1726
1727    #[tokio::test]
1728    async fn test_m7_health_check_returns_zero_for_empty_pool(
1729    ) -> Result<(), Box<dyn std::error::Error>> {
1730        let config = PoolConfigBuilder::new().max_size(5).build()?;
1731        let factory = Arc::new(MockConnectionFactory);
1732        let pool = Pool::new(config, factory)?;
1733
1734        let removed = pool.health_check().await;
1735        assert_eq!(removed, 0);
1736        Ok(())
1737    }
1738
1739    // ==================== 生产 Bug 复现测试 ====================
1740
1741    /// 可追踪创建次数的连接工厂
1742    struct CountingFactory {
1743        count: AtomicU32,
1744    }
1745
1746    impl CountingFactory {
1747        fn new() -> Self {
1748            Self {
1749                count: AtomicU32::new(0),
1750            }
1751        }
1752        fn created_count(&self) -> u32 {
1753            self.count.load(Ordering::SeqCst)
1754        }
1755    }
1756
1757    #[async_trait]
1758    impl ConnectionFactory for CountingFactory {
1759        async fn create(&self) -> Result<Box<dyn Connection>, crate::DbError> {
1760            self.count.fetch_add(1, Ordering::SeqCst);
1761            Ok(Box::new(MockConnection::new()))
1762        }
1763    }
1764
1765    /// 生产 Bug 复现:release() 重置 created_at 导致连接永不过期
1766    ///
1767    /// 症状:生产环境运行 30 分钟后间歇性 "connection timeout"
1768    /// 根因:release() 中 created_at 被重置为 now(),max_lifetime 检查永远不触发
1769    /// 期望:超过 max_lifetime 的连接应被回收并创建新连接
1770    #[tokio::test]
1771    async fn test_production_bug_max_lifetime_never_expires(
1772    ) -> Result<(), Box<dyn std::error::Error>> {
1773        // 注意:PoolConfigBuilder::max_lifetime() 接受秒,这里需要毫秒级精度
1774        // 所以直接构造 PoolConfig
1775        let config = PoolConfig {
1776            max_size: 5,
1777            min_idle: 0,
1778            acquire_timeout: Duration::from_secs(30),
1779            idle_timeout: Duration::from_secs(600),
1780            max_lifetime: Duration::from_millis(100), // 100ms
1781            connection_timeout: Duration::from_secs(10),
1782            tls: None,
1783            query_timeout: None,
1784            max_rows: None,
1785            memory_limit: None,
1786            on_event: None,
1787            test_before_acquire: false,
1788        };
1789        let factory = Arc::new(CountingFactory::new());
1790        let pool = Pool::new(config, factory.clone())?;
1791
1792        // 1. 创建连接
1793        let conn = pool.acquire().await?;
1794        assert_eq!(factory.created_count(), 1, "应创建 1 个连接");
1795
1796        // 2. 归还连接(bug:重置 created_at)
1797        pool.release(conn).await;
1798
1799        // 3. 等待超过 max_lifetime
1800        tokio::time::sleep(Duration::from_millis(150)).await;
1801
1802        // 4. 再次获取 — 应检测到连接过期,创建新连接
1803        let conn2 = pool.acquire().await?;
1804
1805        // 5. 验证:如果 bug 存在,factory.created_count() 仍为 1(连接被复用,未过期)
1806        //         如果修复,factory.created_count() 应为 2(旧连接过期,创建新连接)
1807        assert_eq!(
1808            factory.created_count(),
1809            2,
1810            "超过 max_lifetime 后应创建新连接(旧连接应被回收)"
1811        );
1812
1813        pool.release(conn2).await;
1814        Ok(())
1815    }
1816
1817    // ==================== PooledConnection::Drop 自动归还测试 ====================
1818
1819    /// 验证 PooledConnection drop 时自动归还连接到池
1820    ///
1821    /// 修复前:PooledConnection 未实现 Drop,drop 时连接丢失,池耗尽
1822    /// 修复后:Drop 时 spawn 异步 release,连接自动归还
1823    #[tokio::test]
1824    async fn test_drop_auto_release_connection() -> Result<(), Box<dyn std::error::Error>> {
1825        let config = PoolConfigBuilder::new().max_size(2).build()?;
1826        let factory = Arc::new(CountingFactory::new());
1827        let pool = Pool::new(config, factory.clone())?;
1828
1829        // 1. acquire 一个连接(不显式 release)
1830        {
1831            let _conn = pool.acquire().await?;
1832            assert_eq!(factory.created_count(), 1, "应创建 1 个连接");
1833            let status = pool.status().await;
1834            assert_eq!(status.active, 1, "active 应为 1");
1835            assert_eq!(status.idle, 0, "idle 应为 0");
1836            // _conn 在此 drop
1837        }
1838
1839        // 2. 等待 Drop spawn 的异步 release 完成
1840        tokio::time::sleep(Duration::from_millis(50)).await;
1841
1842        // 3. 验证连接已自动归还到 idle 队列
1843        let status = pool.status().await;
1844        assert_eq!(status.idle, 1, "Drop 后连接应自动归还,idle 应为 1");
1845        assert_eq!(status.active, 1, "total_count 应为 1");
1846        assert_eq!(factory.created_count(), 1, "应复用归还的连接,不创建新连接");
1847        Ok(())
1848    }
1849
1850    /// 验证 Drop 自动归还后,连接可被再次 acquire 复用
1851    #[tokio::test]
1852    async fn test_drop_auto_release_then_reuse() -> Result<(), Box<dyn std::error::Error>> {
1853        let config = PoolConfigBuilder::new().max_size(1).build()?;
1854        let factory = Arc::new(CountingFactory::new());
1855        let pool = Pool::new(config, factory.clone())?;
1856
1857        // max_size=1,如果 Drop 不归还,第二次 acquire 会超时
1858        {
1859            let _conn = pool.acquire().await?;
1860        }
1861
1862        // 等待 Drop spawn 的 release 完成
1863        tokio::time::sleep(Duration::from_millis(50)).await;
1864
1865        // 再次 acquire 应复用归还的连接,不创建新连接
1866        let conn = pool.acquire().await?;
1867        assert_eq!(factory.created_count(), 1, "应复用归还的连接,不创建新连接");
1868
1869        pool.release(conn).await;
1870        Ok(())
1871    }
1872
1873    /// 验证 into_inner 后 Drop 不归还(连接被消费)
1874    #[tokio::test]
1875    async fn test_into_inner_does_not_return_to_pool() -> Result<(), Box<dyn std::error::Error>> {
1876        let config = PoolConfigBuilder::new().max_size(2).build()?;
1877        let factory = Arc::new(CountingFactory::new());
1878        let pool = Pool::new(config, factory.clone())?;
1879
1880        let conn = pool.acquire().await?;
1881        assert_eq!(factory.created_count(), 1);
1882
1883        // into_inner 消费连接,pool 字段设为 None
1884        let _raw_conn = conn.into_inner();
1885
1886        // 等待一段时间,确保不会有 Drop spawn
1887        tokio::time::sleep(Duration::from_millis(50)).await;
1888
1889        let status = pool.status().await;
1890        assert_eq!(status.idle, 0, "into_inner 后连接不应归还");
1891        assert_eq!(status.active, 1, "total_count 仍为 1(连接被外部持有)");
1892        Ok(())
1893    }
1894
1895    /// 验证显式 release 后 Drop 不会重复归还
1896    #[tokio::test]
1897    async fn test_explicit_release_no_double_return() -> Result<(), Box<dyn std::error::Error>> {
1898        let config = PoolConfigBuilder::new().max_size(2).build()?;
1899        let factory = Arc::new(CountingFactory::new());
1900        let pool = Pool::new(config, factory.clone())?;
1901
1902        let conn = pool.acquire().await?;
1903        pool.release(conn).await;
1904
1905        let status = pool.status().await;
1906        assert_eq!(status.idle, 1, "release 后 idle 应为 1");
1907
1908        // 再次 acquire + release 验证不会重复
1909        let conn = pool.acquire().await?;
1910        pool.release(conn).await;
1911
1912        let status = pool.status().await;
1913        assert_eq!(status.idle, 1, "再次 release 后 idle 仍应为 1(不重复)");
1914        assert_eq!(status.active, 1, "total_count 应为 1");
1915        Ok(())
1916    }
1917
1918    // ========================================================================
1919    // G-SX-4:query_stream 游标流式查询测试
1920    // ========================================================================
1921
1922    /// 带预设行数据的模拟连接,用于测试 `query_stream` 默认实现。
1923    struct CursorMockConn {
1924        rows: QueryRows,
1925        call_count: usize,
1926    }
1927
1928    impl CursorMockConn {
1929        fn new(rows: QueryRows) -> Self {
1930            Self {
1931                rows,
1932                call_count: 0,
1933            }
1934        }
1935    }
1936
1937    impl Connection for CursorMockConn {
1938        fn execute<'a>(
1939            &'a mut self,
1940            _sql: &'a str,
1941        ) -> Pin<Box<dyn Future<Output = Result<u64, crate::DbError>> + Send + 'a>> {
1942            Box::pin(async move { Ok(1) })
1943        }
1944
1945        fn query<'a>(
1946            &'a mut self,
1947            _sql: &'a str,
1948        ) -> Pin<Box<dyn Future<Output = Result<QueryRows, crate::DbError>> + Send + 'a>> {
1949            Box::pin(async move {
1950                self.call_count += 1;
1951                Ok(self.rows.clone())
1952            })
1953        }
1954
1955        fn begin_transaction<'a>(
1956            &'a mut self,
1957        ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>> {
1958            Box::pin(async move { Ok(()) })
1959        }
1960
1961        fn commit<'a>(
1962            &'a mut self,
1963        ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>> {
1964            Box::pin(async move { Ok(()) })
1965        }
1966
1967        fn rollback<'a>(
1968            &'a mut self,
1969        ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>> {
1970            Box::pin(async move { Ok(()) })
1971        }
1972
1973        fn is_connected(&self) -> bool {
1974            true
1975        }
1976
1977        fn ping<'a>(&'a mut self) -> Pin<Box<dyn Future<Output = bool> + Send + 'a>> {
1978            Box::pin(async move { true })
1979        }
1980
1981        fn close<'a>(
1982            &'a mut self,
1983        ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>> {
1984            Box::pin(async move { Ok(()) })
1985        }
1986    }
1987
1988    /// 模拟游标适配器:覆盖 `query_stream` 以逐行 yield,而非全量收集。
1989    struct CursorOverrideMockConn {
1990        rows: Vec<crate::value::Value>,
1991        yielded: usize,
1992    }
1993
1994    impl CursorOverrideMockConn {
1995        fn new(rows: Vec<crate::value::Value>) -> Self {
1996            Self { rows, yielded: 0 }
1997        }
1998    }
1999
2000    impl Connection for CursorOverrideMockConn {
2001        fn execute<'a>(
2002            &'a mut self,
2003            _sql: &'a str,
2004        ) -> Pin<Box<dyn Future<Output = Result<u64, crate::DbError>> + Send + 'a>> {
2005            Box::pin(async move { Ok(1) })
2006        }
2007
2008        fn query<'a>(
2009            &'a mut self,
2010            _sql: &'a str,
2011        ) -> Pin<Box<dyn Future<Output = Result<QueryRows, crate::DbError>> + Send + 'a>> {
2012            // 全量收集实现(不应被 cursor override 调用)
2013            Box::pin(async move {
2014                Ok(self
2015                    .rows
2016                    .iter()
2017                    .map(|v| {
2018                        let mut m = std::collections::HashMap::new();
2019                        m.insert("v".to_string(), v.clone());
2020                        m
2021                    })
2022                    .collect())
2023            })
2024        }
2025
2026        /// G-SX-4:覆盖 query_stream,逐行 yield 模拟真游标
2027        fn query_stream<'a>(
2028            &'a mut self,
2029            _sql: &'a str,
2030        ) -> Pin<Box<dyn futures::Stream<Item = QueryStreamItem> + Send + 'a>> {
2031            Box::pin(futures::stream::iter(
2032                self.rows
2033                    .iter()
2034                    .enumerate()
2035                    .map(|(i, v)| {
2036                        self.yielded = i + 1;
2037                        let mut m = std::collections::HashMap::new();
2038                        m.insert("v".to_string(), v.clone());
2039                        Ok(m)
2040                    })
2041                    .collect::<Vec<_>>(),
2042            ))
2043        }
2044
2045        fn begin_transaction<'a>(
2046            &'a mut self,
2047        ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>> {
2048            Box::pin(async move { Ok(()) })
2049        }
2050
2051        fn commit<'a>(
2052            &'a mut self,
2053        ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>> {
2054            Box::pin(async move { Ok(()) })
2055        }
2056
2057        fn rollback<'a>(
2058            &'a mut self,
2059        ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>> {
2060            Box::pin(async move { Ok(()) })
2061        }
2062
2063        fn is_connected(&self) -> bool {
2064            true
2065        }
2066
2067        fn ping<'a>(&'a mut self) -> Pin<Box<dyn Future<Output = bool> + Send + 'a>> {
2068            Box::pin(async move { true })
2069        }
2070
2071        fn close<'a>(
2072            &'a mut self,
2073        ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>> {
2074            Box::pin(async move { Ok(()) })
2075        }
2076    }
2077
2078    /// G-SX-4 测试 1:默认 query_stream 逐行 yield 全量结果
2079    #[tokio::test]
2080    async fn test_query_stream_default_impl_yields_all_rows() {
2081        use futures::StreamExt;
2082        let rows: QueryRows = vec![
2083            std::collections::HashMap::from([
2084                ("id".to_string(), crate::value::Value::I64(1)),
2085                (
2086                    "name".to_string(),
2087                    crate::value::Value::String("alice".to_string()),
2088                ),
2089            ]),
2090            std::collections::HashMap::from([
2091                ("id".to_string(), crate::value::Value::I64(2)),
2092                (
2093                    "name".to_string(),
2094                    crate::value::Value::String("bob".to_string()),
2095                ),
2096            ]),
2097            std::collections::HashMap::from([
2098                ("id".to_string(), crate::value::Value::I64(3)),
2099                (
2100                    "name".to_string(),
2101                    crate::value::Value::String("carol".to_string()),
2102                ),
2103            ]),
2104        ];
2105        let mut conn = CursorMockConn::new(rows);
2106        let mut stream = conn.query_stream("SELECT id, name FROM users");
2107        let mut received: Vec<QueryStreamItem> = Vec::new();
2108        while let Some(item) = stream.next().await {
2109            received.push(item);
2110        }
2111        assert_eq!(received.len(), 3, "应收到 3 行");
2112        assert!(received.iter().all(|r| r.is_ok()), "所有项应为 Ok");
2113        drop(stream);
2114        assert_eq!(conn.call_count, 1, "默认实现应调用 query() 一次");
2115    }
2116
2117    /// G-SX-4 测试 2:默认 query_stream 空结果集
2118    #[tokio::test]
2119    async fn test_query_stream_default_empty_result() {
2120        use futures::StreamExt;
2121        let mut conn = CursorMockConn::new(Vec::new());
2122        let mut stream = conn.query_stream("SELECT * FROM empty_table");
2123        let mut count = 0;
2124        while let Some(_item) = stream.next().await {
2125            count += 1;
2126        }
2127        assert_eq!(count, 0, "空结果集应产生 0 项");
2128    }
2129
2130    /// G-SX-4 测试 3:默认 query_stream 错误传播
2131    #[tokio::test]
2132    async fn test_query_stream_default_error_propagation() {
2133        use futures::StreamExt;
2134        // 创建一个会返回错误的 mock
2135        struct ErrorMockConn;
2136        impl Connection for ErrorMockConn {
2137            fn execute<'a>(
2138                &'a mut self,
2139                _sql: &'a str,
2140            ) -> Pin<Box<dyn Future<Output = Result<u64, crate::DbError>> + Send + 'a>>
2141            {
2142                Box::pin(async move { Ok(1) })
2143            }
2144            fn query<'a>(
2145                &'a mut self,
2146                _sql: &'a str,
2147            ) -> Pin<Box<dyn Future<Output = Result<QueryRows, crate::DbError>> + Send + 'a>>
2148            {
2149                Box::pin(async move { Err(crate::DbError::Internal("query failed".to_string())) })
2150            }
2151            fn begin_transaction<'a>(
2152                &'a mut self,
2153            ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>> {
2154                Box::pin(async move { Ok(()) })
2155            }
2156            fn commit<'a>(
2157                &'a mut self,
2158            ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>> {
2159                Box::pin(async move { Ok(()) })
2160            }
2161            fn rollback<'a>(
2162                &'a mut self,
2163            ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>> {
2164                Box::pin(async move { Ok(()) })
2165            }
2166            fn is_connected(&self) -> bool {
2167                true
2168            }
2169            fn ping<'a>(&'a mut self) -> Pin<Box<dyn Future<Output = bool> + Send + 'a>> {
2170                Box::pin(async move { true })
2171            }
2172            fn close<'a>(
2173                &'a mut self,
2174            ) -> Pin<Box<dyn Future<Output = Result<(), crate::DbError>> + Send + 'a>> {
2175                Box::pin(async move { Ok(()) })
2176            }
2177        }
2178        let mut conn = ErrorMockConn;
2179        let mut stream = conn.query_stream("SELECT * FROM bad_table");
2180        let item = stream.next().await;
2181        assert!(item.is_some(), "应产生一项");
2182        assert!(item.unwrap().is_err(), "该项应为 Err");
2183    }
2184
2185    /// G-SX-4 测试 4:覆盖 query_stream 的适配器逐行 yield(模拟真游标)
2186    #[tokio::test]
2187    async fn test_query_stream_override_yields_rows_one_by_one() {
2188        use futures::StreamExt;
2189        let rows = vec![
2190            crate::value::Value::I64(10),
2191            crate::value::Value::I64(20),
2192            crate::value::Value::I64(30),
2193            crate::value::Value::I64(40),
2194            crate::value::Value::I64(50),
2195        ];
2196        let mut conn = CursorOverrideMockConn::new(rows);
2197        let values: Vec<i64> = {
2198            let mut stream = conn.query_stream("SELECT v FROM seq");
2199            let mut vals: Vec<i64> = Vec::new();
2200            while let Some(Ok(row)) = stream.next().await {
2201                if let crate::value::Value::I64(v) = row.get("v").unwrap() {
2202                    vals.push(*v);
2203                }
2204            }
2205            vals
2206        };
2207        assert_eq!(values, vec![10, 20, 30, 40, 50], "应按顺序收到全部 5 行");
2208        assert_eq!(conn.yielded, 5, "应逐行 yield 5 次(真游标覆盖)");
2209    }
2210
2211    /// G-SX-4 测试 5:覆盖 query_stream 提前 drop 流(消费者中断)
2212    #[tokio::test]
2213    async fn test_query_stream_override_early_drop() {
2214        use futures::StreamExt;
2215        let rows = vec![
2216            crate::value::Value::I64(1),
2217            crate::value::Value::I64(2),
2218            crate::value::Value::I64(3),
2219        ];
2220        let mut conn = CursorOverrideMockConn::new(rows);
2221        {
2222            let mut stream = conn.query_stream("SELECT v FROM seq");
2223            let first = stream.next().await;
2224            assert!(first.is_some(), "第一项应存在");
2225            // 提前 drop stream — 模拟消费者中断
2226            drop(stream);
2227        }
2228        // 连接仍可用
2229        assert!(conn.is_connected(), "提前 drop 流后连接仍应可用");
2230    }
2231}