Skip to main content

compio_pool/
builder.rs

1//! Build a [`Pool`] from a manager and a handful of knobs — the bb8 `Builder`,
2//! minus the settings that only make sense for a single shared pool.
3
4use std::{marker::PhantomData, time::Duration};
5
6use crate::{manage::ManageConnection, pool::Pool};
7
8/// The resolved configuration every thread's pool reads. Cheap to copy; it lives
9/// behind the pool's `Arc` and is shared read-only across threads.
10#[derive(Clone, Copy, Debug)]
11pub(crate) struct PoolConfig {
12    pub max_size: u32,
13    pub min_idle: u32,
14    pub connection_timeout: Duration,
15    pub idle_timeout: Option<Duration>,
16    pub max_lifetime: Option<Duration>,
17    pub test_on_check_out: bool,
18}
19
20impl Default for PoolConfig {
21    fn default() -> Self {
22        Self {
23            max_size: 10,
24            min_idle: 0,
25            connection_timeout: Duration::from_secs(30),
26            idle_timeout: Some(Duration::from_secs(10 * 60)),
27            max_lifetime: Some(Duration::from_secs(30 * 60)),
28            test_on_check_out: true,
29        }
30    }
31}
32
33/// Configures and builds a [`Pool`].
34///
35/// Every size here is **per thread**: [`max_size`](Self::max_size) caps one
36/// thread's [`LocalPool`](crate::LocalPool), not the process. A 48-core server
37/// with `max_size(16)` can therefore hold up to `48 × 16` connections, 16 of
38/// them to any one thread's ring.
39///
40/// Defaults match bb8: `max_size` 10, `min_idle` 0, `connection_timeout` 30s,
41/// `idle_timeout` 10 min, `max_lifetime` 30 min, `test_on_check_out` on.
42pub struct Builder<M: ManageConnection> {
43    config: PoolConfig,
44    _marker: PhantomData<fn() -> M>,
45}
46
47impl<M: ManageConnection> Default for Builder<M> {
48    fn default() -> Self {
49        Self {
50            config: PoolConfig::default(),
51            _marker: PhantomData,
52        }
53    }
54}
55
56impl<M: ManageConnection> Builder<M> {
57    /// A builder with the default settings.
58    pub fn new() -> Self {
59        Self::default()
60    }
61
62    /// The most connections one thread's pool keeps open at once (idle plus
63    /// checked out). Default 10.
64    pub fn max_size(mut self, n: u32) -> Self {
65        self.config.max_size = n;
66        self
67    }
68
69    /// How many connections each thread opens up front and keeps idle, created
70    /// by [`LocalPool::warm`](crate::LocalPool::warm). Capped at
71    /// [`max_size`](Self::max_size). Default 0.
72    pub fn min_idle(mut self, n: u32) -> Self {
73        self.config.min_idle = n;
74        self
75    }
76
77    /// How long [`get`](crate::LocalPool::get) waits — for a free slot and a live
78    /// connection — before returning [`RunError::TimedOut`](crate::RunError::TimedOut).
79    /// Default 30s.
80    pub fn connection_timeout(mut self, d: Duration) -> Self {
81        self.config.connection_timeout = d;
82        self
83    }
84
85    /// Drop an idle connection that has gone unused for this long. `None` keeps
86    /// idle connections forever. Default 10 minutes.
87    pub fn idle_timeout(mut self, d: Option<Duration>) -> Self {
88        self.config.idle_timeout = d;
89        self
90    }
91
92    /// Drop a connection older than this, idle or not, the next time it is
93    /// checked out or returned. `None` never retires on age. Default 30 minutes.
94    pub fn max_lifetime(mut self, d: Option<Duration>) -> Self {
95        self.config.max_lifetime = d;
96        self
97    }
98
99    /// Call [`ManageConnection::is_valid`] on a reused connection as it is
100    /// checked out. Default `true`.
101    pub fn test_on_check_out(mut self, yes: bool) -> Self {
102        self.config.test_on_check_out = yes;
103        self
104    }
105
106    /// Finish, producing the `Send + Clone` [`Pool`] blueprint.
107    ///
108    /// # Panics
109    ///
110    /// If `max_size` is 0.
111    pub fn build(self, manager: M) -> Pool<M> {
112        assert!(self.config.max_size > 0, "max_size must be at least 1");
113        let mut config = self.config;
114        config.min_idle = config.min_idle.min(config.max_size);
115        Pool::new(manager, config)
116    }
117}