1use crate::error::CamelError;
2use crate::exchange::Exchange;
3use std::sync::Arc;
4use std::time::Duration;
5
6pub type MulticastAggregationFn = Arc<dyn Fn(Exchange, Exchange) -> Exchange + Send + Sync>;
7
8#[derive(Clone, Default)]
9pub enum MulticastStrategy {
10 #[default]
11 LastWins,
12 CollectAll,
13 Original,
14 Custom(MulticastAggregationFn),
15}
16
17impl std::fmt::Debug for MulticastStrategy {
18 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
19 match self {
20 MulticastStrategy::LastWins => f.write_str("LastWins"),
21 MulticastStrategy::CollectAll => f.write_str("CollectAll"),
22 MulticastStrategy::Original => f.write_str("Original"),
23 MulticastStrategy::Custom(_) => f.write_str("Custom(..)"),
24 }
25 }
26}
27
28#[derive(Clone)]
29pub struct MulticastConfig {
30 pub parallel: bool,
31 pub parallel_limit: Option<usize>,
32 pub stop_on_exception: bool,
33 pub timeout: Option<Duration>,
34 pub aggregation: MulticastStrategy,
35}
36
37impl std::fmt::Debug for MulticastConfig {
38 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
39 f.debug_struct("MulticastConfig")
40 .field("parallel", &self.parallel)
41 .field("parallel_limit", &self.parallel_limit)
42 .field("stop_on_exception", &self.stop_on_exception)
43 .field("timeout", &self.timeout)
44 .field("aggregation", &self.aggregation)
45 .finish()
46 }
47}
48
49impl MulticastConfig {
50 pub fn new() -> Self {
51 Self {
52 parallel: false,
53 parallel_limit: None,
54 stop_on_exception: false,
55 timeout: None,
56 aggregation: MulticastStrategy::default(),
57 }
58 }
59
60 pub fn parallel(mut self, parallel: bool) -> Self {
61 self.parallel = parallel;
62 self
63 }
64
65 pub fn parallel_limit(mut self, limit: usize) -> Self {
66 self.parallel_limit = Some(limit);
67 self
68 }
69
70 pub fn stop_on_exception(mut self, stop: bool) -> Self {
71 self.stop_on_exception = stop;
72 self
73 }
74
75 pub fn timeout(mut self, duration: Duration) -> Self {
76 self.timeout = Some(duration);
77 self
78 }
79
80 pub fn aggregation(mut self, strategy: MulticastStrategy) -> Self {
81 self.aggregation = strategy;
82 self
83 }
84
85 pub fn validate(&self) -> Result<(), CamelError> {
90 if self.parallel && self.parallel_limit == Some(0) {
91 return Err(CamelError::Config(
92 "multicast parallel_limit must be > 0".to_string(),
93 ));
94 }
95 Ok(())
96 }
97}
98
99impl Default for MulticastConfig {
100 fn default() -> Self {
101 Self::new()
102 }
103}
104
105#[cfg(test)]
106mod tests {
107 use super::*;
108 use std::time::Duration;
109
110 #[test]
111 fn test_multicast_config_defaults() {
112 let config = MulticastConfig::new();
113 assert!(!config.parallel);
114 assert!(config.parallel_limit.is_none());
115 assert!(!config.stop_on_exception);
116 assert!(config.timeout.is_none());
117 assert!(matches!(config.aggregation, MulticastStrategy::LastWins));
118 }
119
120 #[test]
121 fn test_multicast_config_builder() {
122 let config = MulticastConfig::new()
123 .parallel(true)
124 .parallel_limit(4)
125 .stop_on_exception(true)
126 .timeout(Duration::from_millis(500));
127
128 assert!(config.parallel);
129 assert_eq!(config.parallel_limit, Some(4));
130 assert!(config.stop_on_exception);
131 assert_eq!(config.timeout, Some(Duration::from_millis(500)));
132 }
133}