1use crate::metrics_utils::describe_metrics;
2use crate::{Manager, Pool};
3use std::marker::PhantomData;
4use std::time::Duration;
5
6const DEFAULT_MAX_IDLE_CONNS: u64 = 2;
7const DEFAULT_MAX_OPEN_CONNS: u64 = 10;
8const DEFAULT_BAD_CONN_RETRIES: u32 = 2;
9
10pub(crate) struct Config {
11 pub max_open: u64,
12 pub max_idle: u64,
13 pub max_lifetime: Option<Duration>,
14 pub max_idle_lifetime: Option<Duration>,
15 pub clean_rate: Duration,
16 pub max_bad_conn_retries: u32,
17 pub get_timeout: Option<Duration>,
18 pub health_check_interval: Option<Duration>,
19 pub health_check: bool,
20}
21
22impl Config {
23 pub fn split(self) -> (ShareConfig, InternalConfig) {
24 let share = ShareConfig {
25 clean_rate: self.clean_rate,
26 max_bad_conn_retries: self.max_bad_conn_retries,
27 get_timeout: self.get_timeout,
28 health_check: self.health_check,
29 health_check_interval: self.health_check_interval,
30 };
31
32 let internal = InternalConfig {
33 max_open: self.max_open,
34 max_idle: self.max_idle,
35 max_lifetime: self.max_lifetime,
36 max_idle_lifetime: self.max_idle_lifetime,
37 };
38
39 (share, internal)
40 }
41}
42
43pub(crate) struct ShareConfig {
44 pub clean_rate: Duration,
45 pub max_bad_conn_retries: u32,
46 pub get_timeout: Option<Duration>,
47 pub health_check: bool,
48 pub health_check_interval: Option<Duration>,
49}
50
51#[derive(Clone)]
52pub(crate) struct InternalConfig {
53 pub max_open: u64,
54 pub max_idle: u64,
55 pub max_lifetime: Option<Duration>,
56 pub max_idle_lifetime: Option<Duration>,
57}
58
59pub struct Builder<M> {
61 max_open: u64,
62 max_idle: Option<u64>,
63 max_lifetime: Option<Duration>,
64 max_idle_lifetime: Option<Duration>,
65 clean_rate: Duration,
66 max_bad_conn_retries: u32,
67 get_timeout: Option<Duration>,
68 health_check_interval: Option<Duration>,
69 health_check: bool,
70 _keep: PhantomData<M>,
71}
72
73impl<M> Default for Builder<M> {
74 fn default() -> Self {
75 Self {
76 max_open: DEFAULT_MAX_OPEN_CONNS,
77 max_idle: None,
78 max_lifetime: None,
79 max_idle_lifetime: None,
80 clean_rate: Duration::from_secs(1),
81 max_bad_conn_retries: DEFAULT_BAD_CONN_RETRIES,
82 get_timeout: Some(Duration::from_secs(30)),
83 _keep: PhantomData,
84 health_check: true,
85 health_check_interval: None,
86 }
87 }
88}
89
90impl<M: Manager> Builder<M> {
91 pub fn new() -> Self {
95 Default::default()
96 }
97
98 pub fn max_open(mut self, max_open: u64) -> Self {
103 self.max_open = max_open;
104 self
105 }
106
107 pub fn max_idle(mut self, max_idle: u64) -> Self {
114 self.max_idle = Some(max_idle);
115 self
116 }
117
118 pub fn test_on_check_out(mut self, health_check: bool) -> Builder<M> {
123 self.health_check = health_check;
124 self
125 }
126
127 pub fn max_lifetime(mut self, max_lifetime: Option<Duration>) -> Self {
138 assert_ne!(
139 max_lifetime,
140 Some(Duration::from_secs(0)),
141 "max_lifetime must be positive"
142 );
143 self.max_lifetime = max_lifetime;
144 self
145 }
146
147 pub fn max_idle_lifetime(mut self, max_idle_lifetime: Option<Duration>) -> Self {
159 assert_ne!(
160 max_idle_lifetime,
161 Some(Duration::from_secs(0)),
162 "max_idle_lifetime must be positive"
163 );
164 self.max_idle_lifetime = max_idle_lifetime;
165 self
166 }
167
168 pub fn get_timeout(mut self, get_timeout: Option<Duration>) -> Self {
180 assert_ne!(
181 get_timeout,
182 Some(Duration::from_secs(0)),
183 "get_timeout must be positive"
184 );
185
186 self.get_timeout = get_timeout;
187 self
188 }
189
190 pub fn health_check_interval(mut self, health_check_interval: Option<Duration>) -> Self {
205 assert_ne!(
206 health_check_interval,
207 Some(Duration::from_secs(0)),
208 "health_check_interval must be positive"
209 );
210
211 self.health_check_interval = health_check_interval;
212 self
213 }
214 #[doc(hidden)]
216 #[allow(dead_code)]
217 pub fn clean_rate(mut self, clean_rate: Duration) -> Builder<M> {
218 assert!(
219 clean_rate > Duration::from_secs(0),
220 "connection_timeout must be positive"
221 );
222
223 if clean_rate > Duration::from_secs(1) {
224 self.clean_rate = clean_rate;
225 }
226
227 self
228 }
229
230 pub fn build(self, manager: M) -> Pool<M> {
236 use std::cmp;
237
238 describe_metrics();
239 let max_idle = self
240 .max_idle
241 .unwrap_or_else(|| cmp::min(self.max_open, DEFAULT_MAX_IDLE_CONNS));
242
243 assert!(
244 self.max_open >= max_idle,
245 "max_idle must be no larger than max_open"
246 );
247
248 let config = Config {
249 max_open: self.max_open,
250 max_idle,
251 max_lifetime: self.max_lifetime,
252 max_idle_lifetime: self.max_idle_lifetime,
253 get_timeout: self.get_timeout,
254 clean_rate: self.clean_rate,
255 max_bad_conn_retries: self.max_bad_conn_retries,
256 health_check: self.health_check,
257 health_check_interval: self.health_check_interval,
258 };
259
260 Pool::new_inner(manager, config)
261 }
262}