1use serde::{Deserialize, Serialize};
2use std::time::Duration;
3
4#[derive(Debug, Clone, Serialize, Deserialize)]
6pub struct RabbitConfig {
7 pub connection_string: String,
9
10 pub virtual_host: Option<String>,
12
13 pub connection_timeout: Option<Duration>,
15
16 pub heartbeat: Option<Duration>,
18
19 pub retry_config: RetryConfig,
21
22 pub health_check: HealthCheckConfig,
24
25 pub pool_config: PoolConfig,
27}
28
29impl RabbitConfig {
30 pub fn builder() -> RabbitConfigBuilder {
32 RabbitConfigBuilder::new()
33 }
34}
35
36#[derive(Debug, Clone)]
38pub struct RabbitConfigBuilder {
39 connection_string: String,
40 virtual_host: Option<String>,
41 connection_timeout: Option<Duration>,
42 heartbeat: Option<Duration>,
43 retry_config: RetryConfig,
44 health_check: HealthCheckConfig,
45 pool_config: PoolConfig,
46}
47
48impl RabbitConfigBuilder {
49 pub fn new() -> Self {
51 Self {
52 connection_string: "amqp://localhost:5672".to_string(),
53 virtual_host: Some("/".to_string()),
54 connection_timeout: Some(Duration::from_secs(30)),
55 heartbeat: Some(Duration::from_secs(60)),
56 retry_config: RetryConfig::default(),
57 health_check: HealthCheckConfig::default(),
58 pool_config: PoolConfig::default(),
59 }
60 }
61
62 pub fn connection_string<S: Into<String>>(mut self, connection_string: S) -> Self {
64 self.connection_string = connection_string.into();
65 self
66 }
67
68 pub fn virtual_host<S: Into<String>>(mut self, virtual_host: S) -> Self {
70 self.virtual_host = Some(virtual_host.into());
71 self
72 }
73
74 pub fn no_virtual_host(mut self) -> Self {
76 self.virtual_host = None;
77 self
78 }
79
80 pub fn connection_timeout(mut self, timeout: Duration) -> Self {
82 self.connection_timeout = Some(timeout);
83 self
84 }
85
86 pub fn no_connection_timeout(mut self) -> Self {
88 self.connection_timeout = None;
89 self
90 }
91
92 pub fn heartbeat(mut self, heartbeat: Duration) -> Self {
94 self.heartbeat = Some(heartbeat);
95 self
96 }
97
98 pub fn no_heartbeat(mut self) -> Self {
100 self.heartbeat = None;
101 self
102 }
103
104 pub fn retry_config(mut self, retry_config: RetryConfig) -> Self {
106 self.retry_config = retry_config;
107 self
108 }
109
110 pub fn retry<F>(mut self, f: F) -> Self
112 where
113 F: FnOnce(RetryConfigBuilder) -> RetryConfigBuilder,
114 {
115 self.retry_config = f(RetryConfigBuilder::new()).build();
116 self
117 }
118
119 pub fn health_check(mut self, health_check: HealthCheckConfig) -> Self {
121 self.health_check = health_check;
122 self
123 }
124
125 pub fn health<F>(mut self, f: F) -> Self
127 where
128 F: FnOnce(HealthCheckConfigBuilder) -> HealthCheckConfigBuilder,
129 {
130 self.health_check = f(HealthCheckConfigBuilder::new()).build();
131 self
132 }
133
134 pub fn pool_config(mut self, pool_config: PoolConfig) -> Self {
136 self.pool_config = pool_config;
137 self
138 }
139
140 pub fn pool<F>(mut self, f: F) -> Self
142 where
143 F: FnOnce(PoolConfigBuilder) -> PoolConfigBuilder,
144 {
145 self.pool_config = f(PoolConfigBuilder::new()).build();
146 self
147 }
148
149 pub fn build(self) -> RabbitConfig {
151 RabbitConfig {
152 connection_string: self.connection_string,
153 virtual_host: self.virtual_host,
154 connection_timeout: self.connection_timeout,
155 heartbeat: self.heartbeat,
156 retry_config: self.retry_config,
157 health_check: self.health_check,
158 pool_config: self.pool_config,
159 }
160 }
161}
162
163impl Default for RabbitConfigBuilder {
164 fn default() -> Self {
165 Self::new()
166 }
167}
168
169impl Default for RabbitConfig {
170 fn default() -> Self {
171 Self {
172 connection_string: "amqp://localhost:5672".to_string(),
173 virtual_host: Some("/".to_string()),
174 connection_timeout: Some(Duration::from_secs(30)),
175 heartbeat: Some(Duration::from_secs(60)),
176 retry_config: RetryConfig::default(),
177 health_check: HealthCheckConfig::default(),
178 pool_config: PoolConfig::default(),
179 }
180 }
181}
182
183#[derive(Debug, Clone, Serialize, Deserialize)]
185pub struct RetryConfig {
186 pub max_retries: u32,
188
189 pub initial_delay: Duration,
191
192 pub max_delay: Duration,
194
195 pub backoff_multiplier: f64,
197
198 pub jitter: f64,
200}
201
202impl RetryConfig {
203 pub fn builder() -> RetryConfigBuilder {
205 RetryConfigBuilder::new()
206 }
207}
208
209#[derive(Debug, Clone)]
211pub struct RetryConfigBuilder {
212 max_retries: u32,
213 initial_delay: Duration,
214 max_delay: Duration,
215 backoff_multiplier: f64,
216 jitter: f64,
217}
218
219impl RetryConfigBuilder {
220 pub fn new() -> Self {
222 Self {
223 max_retries: 3,
224 initial_delay: Duration::from_millis(1000),
225 max_delay: Duration::from_secs(60),
226 backoff_multiplier: 2.0,
227 jitter: 0.1,
228 }
229 }
230
231 pub fn max_retries(mut self, max_retries: u32) -> Self {
233 self.max_retries = max_retries;
234 self
235 }
236
237 pub fn initial_delay(mut self, delay: Duration) -> Self {
239 self.initial_delay = delay;
240 self
241 }
242
243 pub fn max_delay(mut self, delay: Duration) -> Self {
245 self.max_delay = delay;
246 self
247 }
248
249 pub fn backoff_multiplier(mut self, multiplier: f64) -> Self {
251 self.backoff_multiplier = multiplier;
252 self
253 }
254
255 pub fn jitter(mut self, jitter: f64) -> Self {
257 self.jitter = jitter.clamp(0.0, 1.0);
258 self
259 }
260
261 pub fn no_jitter(mut self) -> Self {
263 self.jitter = 0.0;
264 self
265 }
266
267 pub fn aggressive(mut self) -> Self {
269 self.max_retries = 5;
270 self.initial_delay = Duration::from_millis(500);
271 self.max_delay = Duration::from_secs(30);
272 self.backoff_multiplier = 1.5;
273 self.jitter = 0.05;
274 self
275 }
276
277 pub fn conservative(mut self) -> Self {
279 self.max_retries = 2;
280 self.initial_delay = Duration::from_secs(2);
281 self.max_delay = Duration::from_secs(120);
282 self.backoff_multiplier = 3.0;
283 self.jitter = 0.2;
284 self
285 }
286
287 pub fn build(self) -> RetryConfig {
289 RetryConfig {
290 max_retries: self.max_retries,
291 initial_delay: self.initial_delay,
292 max_delay: self.max_delay,
293 backoff_multiplier: self.backoff_multiplier,
294 jitter: self.jitter,
295 }
296 }
297}
298
299impl Default for RetryConfigBuilder {
300 fn default() -> Self {
301 Self::new()
302 }
303}
304
305impl Default for RetryConfig {
306 fn default() -> Self {
307 Self {
308 max_retries: 3,
309 initial_delay: Duration::from_millis(1000),
310 max_delay: Duration::from_secs(60),
311 backoff_multiplier: 2.0,
312 jitter: 0.1,
313 }
314 }
315}
316
317#[derive(Debug, Clone, Serialize, Deserialize)]
319pub struct HealthCheckConfig {
320 pub check_interval: Duration,
322
323 pub check_timeout: Duration,
325
326 pub enabled: bool,
328}
329
330impl HealthCheckConfig {
331 pub fn builder() -> HealthCheckConfigBuilder {
333 HealthCheckConfigBuilder::new()
334 }
335}
336
337#[derive(Debug, Clone)]
339pub struct HealthCheckConfigBuilder {
340 check_interval: Duration,
341 check_timeout: Duration,
342 enabled: bool,
343}
344
345impl HealthCheckConfigBuilder {
346 pub fn new() -> Self {
348 Self {
349 check_interval: Duration::from_secs(30),
350 check_timeout: Duration::from_secs(5),
351 enabled: true,
352 }
353 }
354
355 pub fn check_interval(mut self, interval: Duration) -> Self {
357 self.check_interval = interval;
358 self
359 }
360
361 pub fn check_timeout(mut self, timeout: Duration) -> Self {
363 self.check_timeout = timeout;
364 self
365 }
366
367 pub fn enabled(mut self) -> Self {
369 self.enabled = true;
370 self
371 }
372
373 pub fn disabled(mut self) -> Self {
375 self.enabled = false;
376 self
377 }
378
379 pub fn frequent(mut self) -> Self {
381 self.check_interval = Duration::from_secs(10);
382 self.check_timeout = Duration::from_secs(3);
383 self.enabled = true;
384 self
385 }
386
387 pub fn infrequent(mut self) -> Self {
389 self.check_interval = Duration::from_secs(120);
390 self.check_timeout = Duration::from_secs(10);
391 self.enabled = true;
392 self
393 }
394
395 pub fn build(self) -> HealthCheckConfig {
397 HealthCheckConfig {
398 check_interval: self.check_interval,
399 check_timeout: self.check_timeout,
400 enabled: self.enabled,
401 }
402 }
403}
404
405impl Default for HealthCheckConfigBuilder {
406 fn default() -> Self {
407 Self::new()
408 }
409}
410
411impl Default for HealthCheckConfig {
412 fn default() -> Self {
413 Self {
414 check_interval: Duration::from_secs(30),
415 check_timeout: Duration::from_secs(5),
416 enabled: true,
417 }
418 }
419}
420
421#[derive(Debug, Clone, Serialize, Deserialize)]
423pub struct PoolConfig {
424 pub max_connections: usize,
426
427 pub min_connections: usize,
429
430 pub idle_timeout: Duration,
432}
433
434impl PoolConfig {
435 pub fn builder() -> PoolConfigBuilder {
437 PoolConfigBuilder::new()
438 }
439}
440
441#[derive(Debug, Clone)]
443pub struct PoolConfigBuilder {
444 max_connections: usize,
445 min_connections: usize,
446 idle_timeout: Duration,
447}
448
449impl PoolConfigBuilder {
450 pub fn new() -> Self {
452 Self {
453 max_connections: 10,
454 min_connections: 1,
455 idle_timeout: Duration::from_secs(300),
456 }
457 }
458
459 pub fn max_connections(mut self, max: usize) -> Self {
461 self.max_connections = max;
462 self
463 }
464
465 pub fn min_connections(mut self, min: usize) -> Self {
467 self.min_connections = min;
468 self
469 }
470
471 pub fn idle_timeout(mut self, timeout: Duration) -> Self {
473 self.idle_timeout = timeout;
474 self
475 }
476
477 pub fn high_throughput(mut self) -> Self {
479 self.max_connections = 50;
480 self.min_connections = 5;
481 self.idle_timeout = Duration::from_secs(180);
482 self
483 }
484
485 pub fn low_resource(mut self) -> Self {
487 self.max_connections = 3;
488 self.min_connections = 1;
489 self.idle_timeout = Duration::from_secs(600);
490 self
491 }
492
493 pub fn single_connection(mut self) -> Self {
495 self.max_connections = 1;
496 self.min_connections = 1;
497 self.idle_timeout = Duration::from_secs(3600);
498 self
499 }
500
501 pub fn build(self) -> PoolConfig {
503 PoolConfig {
504 max_connections: self.max_connections,
505 min_connections: self.min_connections.min(self.max_connections),
506 idle_timeout: self.idle_timeout,
507 }
508 }
509}
510
511impl Default for PoolConfigBuilder {
512 fn default() -> Self {
513 Self::new()
514 }
515}
516
517impl Default for PoolConfig {
518 fn default() -> Self {
519 Self {
520 max_connections: 10,
521 min_connections: 1,
522 idle_timeout: Duration::from_secs(300),
523 }
524 }
525}
526
527#[cfg(test)]
528mod tests {
529 use super::*;
530 use std::time::Duration;
531
532 #[test]
533 fn test_rabbit_config_default() {
534 let config = RabbitConfig::default();
535 assert_eq!(config.connection_string, "amqp://localhost:5672");
536 assert_eq!(config.virtual_host, Some("/".to_string()));
537 assert_eq!(config.connection_timeout, Some(Duration::from_secs(30)));
538 assert_eq!(config.heartbeat, Some(Duration::from_secs(60)));
539 }
540
541 #[test]
542 fn test_retry_config_default() {
543 let config = RetryConfig::default();
544 assert_eq!(config.max_retries, 3);
545 assert_eq!(config.initial_delay, Duration::from_millis(1000));
546 assert_eq!(config.max_delay, Duration::from_secs(60));
547 assert_eq!(config.backoff_multiplier, 2.0);
548 assert_eq!(config.jitter, 0.1);
549 }
550
551 #[test]
552 fn test_health_check_config_presets() {
553 use crate::health::HealthCheckConfigExt;
554
555 let conservative = HealthCheckConfig::conservative();
556 assert_eq!(conservative.check_interval, Duration::from_secs(60));
557 assert_eq!(conservative.check_timeout, Duration::from_secs(10));
558 assert!(conservative.enabled);
559
560 let aggressive = HealthCheckConfig::aggressive();
561 assert_eq!(aggressive.check_interval, Duration::from_secs(10));
562 assert_eq!(aggressive.check_timeout, Duration::from_secs(3));
563 assert!(aggressive.enabled);
564
565 let minimal = HealthCheckConfig::minimal();
566 assert_eq!(minimal.check_interval, Duration::from_secs(300));
567 assert_eq!(minimal.check_timeout, Duration::from_secs(15));
568 assert!(minimal.enabled);
569 }
570
571 #[test]
572 fn test_pool_config_default() {
573 let config = PoolConfig::default();
574 assert_eq!(config.max_connections, 10);
575 assert_eq!(config.min_connections, 1);
576 assert_eq!(config.idle_timeout, Duration::from_secs(300));
577 }
578}