Skip to main content

reinhardt_db/pool/
config.rs

1//! Pool configuration
2
3#[non_exhaustive]
4#[derive(Debug, Clone)]
5/// Represents a pool config.
6pub struct PoolConfig {
7	/// The max size.
8	pub max_size: u32,
9	/// The min idle.
10	pub min_idle: Option<u32>,
11	/// The max lifetime.
12	pub max_lifetime: Option<std::time::Duration>,
13	/// The idle timeout.
14	pub idle_timeout: Option<std::time::Duration>,
15	/// The connect timeout.
16	pub connect_timeout: std::time::Duration,
17	/// The max connections.
18	pub max_connections: u32,
19	/// The min connections.
20	pub min_connections: u32,
21	/// The acquire timeout.
22	pub acquire_timeout: std::time::Duration,
23	/// The test before acquire.
24	pub test_before_acquire: bool,
25}
26
27impl Default for PoolConfig {
28	fn default() -> Self {
29		Self {
30			max_size: 10,
31			min_idle: None,
32			max_lifetime: Some(std::time::Duration::from_secs(1800)),
33			idle_timeout: Some(std::time::Duration::from_secs(600)),
34			connect_timeout: std::time::Duration::from_secs(30),
35			max_connections: 10,
36			min_connections: 1,
37			acquire_timeout: std::time::Duration::from_secs(30),
38			test_before_acquire: false,
39		}
40	}
41}
42
43impl PoolConfig {
44	/// Create a new pool configuration with default values
45	///
46	/// # Examples
47	///
48	/// ```rust
49	/// use reinhardt_db::pool::PoolConfig;
50	///
51	/// let config = PoolConfig::new();
52	/// assert_eq!(config.max_connections, 10);
53	/// ```
54	pub fn new() -> Self {
55		Self::default()
56	}
57
58	/// Sets the max connections and returns self for chaining.
59	pub fn with_max_connections(mut self, max: u32) -> Self {
60		self.max_connections = max;
61		self
62	}
63
64	/// Sets the min connections and returns self for chaining.
65	pub fn with_min_connections(mut self, min: u32) -> Self {
66		self.min_connections = min;
67		self
68	}
69
70	/// Sets the connection timeout and returns self for chaining.
71	pub fn with_connection_timeout(mut self, timeout: std::time::Duration) -> Self {
72		self.connect_timeout = timeout;
73		self
74	}
75
76	/// Sets the connect timeout and returns self for chaining.
77	pub fn with_connect_timeout(mut self, timeout: std::time::Duration) -> Self {
78		self.connect_timeout = timeout;
79		self
80	}
81
82	/// Sets the acquire timeout and returns self for chaining.
83	pub fn with_acquire_timeout(mut self, timeout: std::time::Duration) -> Self {
84		self.acquire_timeout = timeout;
85		self
86	}
87
88	/// Sets the max lifetime and returns self for chaining.
89	pub fn with_max_lifetime(mut self, lifetime: Option<std::time::Duration>) -> Self {
90		self.max_lifetime = lifetime;
91		self
92	}
93
94	/// Sets the idle timeout and returns self for chaining.
95	pub fn with_idle_timeout(mut self, timeout: Option<std::time::Duration>) -> Self {
96		self.idle_timeout = timeout;
97		self
98	}
99
100	/// Sets the test before acquire and returns self for chaining.
101	pub fn with_test_before_acquire(mut self, test: bool) -> Self {
102		self.test_before_acquire = test;
103		self
104	}
105
106	/// Performs the validate operation.
107	pub fn validate(&self) -> Result<(), String> {
108		if self.max_connections < self.min_connections {
109			return Err("max_connections must be >= min_connections".to_string());
110		}
111		Ok(())
112	}
113}
114
115#[non_exhaustive]
116#[derive(Debug, Clone, Default)]
117/// Represents a pool options.
118pub struct PoolOptions {
119	/// The config.
120	pub config: PoolConfig,
121}
122
123impl PoolOptions {
124	/// Creates a new instance.
125	pub fn new() -> Self {
126		Self::default()
127	}
128
129	/// Performs the max size operation.
130	pub fn max_size(mut self, max_size: u32) -> Self {
131		self.config.max_size = max_size;
132		self
133	}
134
135	/// Performs the min idle operation.
136	pub fn min_idle(mut self, min_idle: u32) -> Self {
137		self.config.min_idle = Some(min_idle);
138		self
139	}
140}
141
142#[cfg(test)]
143mod tests {
144	use super::*;
145	use std::time::Duration;
146
147	#[test]
148	fn default_config_preserves_all_pool_limits() {
149		let config = PoolConfig::default();
150
151		assert_eq!(config.max_size, 10);
152		assert_eq!(config.min_idle, None);
153		assert_eq!(config.max_lifetime, Some(Duration::from_secs(1800)));
154		assert_eq!(config.idle_timeout, Some(Duration::from_secs(600)));
155		assert_eq!(config.connect_timeout, Duration::from_secs(30));
156		assert_eq!(config.max_connections, 10);
157		assert_eq!(config.min_connections, 1);
158		assert_eq!(config.acquire_timeout, Duration::from_secs(30));
159		assert!(!config.test_before_acquire);
160	}
161
162	#[test]
163	fn builder_chain_updates_every_supported_setting() {
164		let connection_timeout_config =
165			PoolConfig::new().with_connection_timeout(Duration::from_secs(15));
166
167		assert_eq!(
168			connection_timeout_config.connect_timeout,
169			Duration::from_secs(15)
170		);
171
172		let config = PoolConfig::new()
173			.with_max_connections(12)
174			.with_min_connections(4)
175			.with_connection_timeout(Duration::from_secs(15))
176			.with_connect_timeout(Duration::from_secs(20))
177			.with_acquire_timeout(Duration::from_secs(25))
178			.with_max_lifetime(Some(Duration::from_secs(3600)))
179			.with_idle_timeout(Some(Duration::from_secs(900)))
180			.with_test_before_acquire(true);
181
182		assert_eq!(config.max_size, 10);
183		assert_eq!(config.min_idle, None);
184		assert_eq!(config.max_lifetime, Some(Duration::from_secs(3600)));
185		assert_eq!(config.idle_timeout, Some(Duration::from_secs(900)));
186		assert_eq!(config.connect_timeout, Duration::from_secs(20));
187		assert_eq!(config.max_connections, 12);
188		assert_eq!(config.min_connections, 4);
189		assert_eq!(config.acquire_timeout, Duration::from_secs(25));
190		assert!(config.test_before_acquire);
191	}
192
193	#[test]
194	fn validation_accepts_equal_connection_bounds() {
195		let config = PoolConfig::new()
196			.with_max_connections(5)
197			.with_min_connections(5);
198
199		assert_eq!(config.validate(), Ok(()));
200	}
201
202	#[test]
203	fn validation_rejects_minimum_above_maximum() {
204		let config = PoolConfig::new()
205			.with_max_connections(4)
206			.with_min_connections(5);
207
208		assert_eq!(
209			config.validate(),
210			Err("max_connections must be >= min_connections".to_string())
211		);
212	}
213
214	#[test]
215	fn options_builder_preserves_all_other_config_defaults() {
216		let options = PoolOptions::new().max_size(20).min_idle(3);
217		let config = options.config;
218
219		assert_eq!(config.max_size, 20);
220		assert_eq!(config.min_idle, Some(3));
221		assert_eq!(config.max_lifetime, Some(Duration::from_secs(1800)));
222		assert_eq!(config.idle_timeout, Some(Duration::from_secs(600)));
223		assert_eq!(config.connect_timeout, Duration::from_secs(30));
224		assert_eq!(config.max_connections, 10);
225		assert_eq!(config.min_connections, 1);
226		assert_eq!(config.acquire_timeout, Duration::from_secs(30));
227		assert!(!config.test_before_acquire);
228	}
229}