heliosdb_proxy/pool/
config.rs1use super::mode::{PoolingMode, PreparedStatementMode};
6use serde::{Deserialize, Serialize};
7use std::time::Duration;
8
9#[derive(Debug, Clone, Serialize, Deserialize)]
11pub struct PoolModeConfig {
12 #[serde(default)]
14 pub default_mode: PoolingMode,
15
16 #[serde(default = "default_max_pool_size")]
18 pub max_pool_size: u32,
19
20 #[serde(default = "default_min_idle")]
22 pub min_idle: u32,
23
24 #[serde(default = "default_idle_timeout_secs")]
26 pub idle_timeout_secs: u64,
27
28 #[serde(default = "default_max_lifetime_secs")]
30 pub max_lifetime_secs: u64,
31
32 #[serde(default = "default_acquire_timeout_secs")]
34 pub acquire_timeout_secs: u64,
35
36 #[serde(default = "default_reset_query")]
38 pub reset_query: String,
39
40 #[serde(default)]
42 pub prepared_statement_mode: PreparedStatementMode,
43
44 #[serde(default = "default_test_on_acquire")]
46 pub test_on_acquire: bool,
47
48 #[serde(default = "default_validation_query")]
50 pub validation_query: String,
51
52 #[serde(default = "default_queue_timeout_secs")]
54 pub queue_timeout_secs: u64,
55
56 #[serde(default)]
58 pub max_queue_size: u32,
59}
60
61fn default_max_pool_size() -> u32 {
62 100
63}
64
65fn default_min_idle() -> u32 {
66 10
67}
68
69fn default_idle_timeout_secs() -> u64 {
70 600 }
72
73fn default_max_lifetime_secs() -> u64 {
74 3600 }
76
77fn default_acquire_timeout_secs() -> u64 {
78 5
79}
80
81fn default_reset_query() -> String {
82 "DISCARD ALL".to_string()
83}
84
85fn default_test_on_acquire() -> bool {
86 true
87}
88
89fn default_validation_query() -> String {
90 "SELECT 1".to_string()
91}
92
93fn default_queue_timeout_secs() -> u64 {
94 30
95}
96
97impl Default for PoolModeConfig {
98 fn default() -> Self {
99 Self {
100 default_mode: PoolingMode::default(),
101 max_pool_size: default_max_pool_size(),
102 min_idle: default_min_idle(),
103 idle_timeout_secs: default_idle_timeout_secs(),
104 max_lifetime_secs: default_max_lifetime_secs(),
105 acquire_timeout_secs: default_acquire_timeout_secs(),
106 reset_query: default_reset_query(),
107 prepared_statement_mode: PreparedStatementMode::default(),
108 test_on_acquire: default_test_on_acquire(),
109 validation_query: default_validation_query(),
110 queue_timeout_secs: default_queue_timeout_secs(),
111 max_queue_size: 0,
112 }
113 }
114}
115
116impl PoolModeConfig {
117 pub fn session_mode() -> Self {
119 Self {
120 default_mode: PoolingMode::Session,
121 prepared_statement_mode: PreparedStatementMode::Named,
122 ..Default::default()
123 }
124 }
125
126 pub fn transaction_mode() -> Self {
128 Self {
129 default_mode: PoolingMode::Transaction,
130 prepared_statement_mode: PreparedStatementMode::Track,
131 ..Default::default()
132 }
133 }
134
135 pub fn statement_mode() -> Self {
137 Self {
138 default_mode: PoolingMode::Statement,
139 prepared_statement_mode: PreparedStatementMode::Disable,
140 ..Default::default()
141 }
142 }
143
144 pub fn idle_timeout(&self) -> Duration {
146 Duration::from_secs(self.idle_timeout_secs)
147 }
148
149 pub fn max_lifetime(&self) -> Duration {
151 Duration::from_secs(self.max_lifetime_secs)
152 }
153
154 pub fn acquire_timeout(&self) -> Duration {
156 Duration::from_secs(self.acquire_timeout_secs)
157 }
158
159 pub fn queue_timeout(&self) -> Duration {
161 Duration::from_secs(self.queue_timeout_secs)
162 }
163
164 pub fn validate(&self) -> Result<(), String> {
166 if self.max_pool_size == 0 {
167 return Err("max_pool_size must be > 0".to_string());
168 }
169
170 if self.min_idle > self.max_pool_size {
171 return Err("min_idle cannot exceed max_pool_size".to_string());
172 }
173
174 if self.acquire_timeout_secs == 0 {
175 return Err("acquire_timeout_secs must be > 0".to_string());
176 }
177
178 if self.reset_query.is_empty() {
179 return Err("reset_query cannot be empty".to_string());
180 }
181
182 if self.default_mode == PoolingMode::Statement
184 && self.prepared_statement_mode == PreparedStatementMode::Named
185 {
186 return Err(
187 "Statement mode cannot use named prepared statements".to_string()
188 );
189 }
190
191 Ok(())
192 }
193
194 pub fn merge(&mut self, other: &PoolModeConfig) {
196 if other.max_pool_size != default_max_pool_size() {
199 self.max_pool_size = other.max_pool_size;
200 }
201 if other.min_idle != default_min_idle() {
202 self.min_idle = other.min_idle;
203 }
204 if other.idle_timeout_secs != default_idle_timeout_secs() {
205 self.idle_timeout_secs = other.idle_timeout_secs;
206 }
207 if other.reset_query != default_reset_query() {
208 self.reset_query = other.reset_query.clone();
209 }
210 }
211}
212
213#[cfg(test)]
214mod tests {
215 use super::*;
216
217 #[test]
218 fn test_default_config() {
219 let config = PoolModeConfig::default();
220 assert_eq!(config.default_mode, PoolingMode::Session);
221 assert_eq!(config.max_pool_size, 100);
222 assert_eq!(config.min_idle, 10);
223 assert_eq!(config.reset_query, "DISCARD ALL");
224 assert!(config.validate().is_ok());
225 }
226
227 #[test]
228 fn test_session_mode_config() {
229 let config = PoolModeConfig::session_mode();
230 assert_eq!(config.default_mode, PoolingMode::Session);
231 assert_eq!(config.prepared_statement_mode, PreparedStatementMode::Named);
232 }
233
234 #[test]
235 fn test_transaction_mode_config() {
236 let config = PoolModeConfig::transaction_mode();
237 assert_eq!(config.default_mode, PoolingMode::Transaction);
238 assert_eq!(config.prepared_statement_mode, PreparedStatementMode::Track);
239 }
240
241 #[test]
242 fn test_statement_mode_config() {
243 let config = PoolModeConfig::statement_mode();
244 assert_eq!(config.default_mode, PoolingMode::Statement);
245 assert_eq!(
246 config.prepared_statement_mode,
247 PreparedStatementMode::Disable
248 );
249 }
250
251 #[test]
252 fn test_validation() {
253 let mut config = PoolModeConfig::default();
254
255 assert!(config.validate().is_ok());
257
258 config.max_pool_size = 0;
260 assert!(config.validate().is_err());
261 config.max_pool_size = 100;
262
263 config.min_idle = 200;
265 assert!(config.validate().is_err());
266 config.min_idle = 10;
267
268 config.default_mode = PoolingMode::Statement;
270 config.prepared_statement_mode = PreparedStatementMode::Named;
271 assert!(config.validate().is_err());
272 }
273
274 #[test]
275 fn test_durations() {
276 let config = PoolModeConfig::default();
277 assert_eq!(config.idle_timeout(), Duration::from_secs(600));
278 assert_eq!(config.max_lifetime(), Duration::from_secs(3600));
279 assert_eq!(config.acquire_timeout(), Duration::from_secs(5));
280 }
281}