Skip to main content

sz_orm_pool/
pool.rs

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