camel_api/
recipient_list.rs1use std::sync::Arc;
2
3use crate::Exchange;
4use crate::error::CamelError;
5
6pub type RecipientListExpression = Arc<dyn Fn(&Exchange) -> String + Send + Sync>;
7
8#[derive(Clone)]
9pub struct RecipientListConfig {
10 pub expression: RecipientListExpression,
11 pub delimiter: String,
12 pub parallel: bool,
13 pub parallel_limit: Option<usize>,
14 pub stop_on_exception: bool,
15 pub strategy: crate::MulticastStrategy,
16}
17
18impl RecipientListConfig {
19 pub fn new(expression: RecipientListExpression) -> Self {
20 Self {
21 expression,
22 delimiter: ",".to_string(),
23 parallel: false,
24 parallel_limit: None,
25 stop_on_exception: false,
26 strategy: crate::MulticastStrategy::default(),
27 }
28 }
29
30 pub fn delimiter(mut self, d: impl Into<String>) -> Self {
31 self.delimiter = d.into();
32 self
33 }
34
35 pub fn parallel(mut self, parallel: bool) -> Self {
36 self.parallel = parallel;
37 self
38 }
39
40 pub fn parallel_limit(mut self, limit: usize) -> Self {
41 self.parallel_limit = Some(limit);
42 self
43 }
44
45 pub fn stop_on_exception(mut self, stop: bool) -> Self {
46 self.stop_on_exception = stop;
47 self
48 }
49
50 pub fn strategy(mut self, strategy: crate::MulticastStrategy) -> Self {
51 self.strategy = strategy;
52 self
53 }
54
55 pub fn validate(&self) -> Result<(), CamelError> {
60 if self.parallel && self.parallel_limit == Some(0) {
61 return Err(CamelError::Config(
62 "recipient_list parallel_limit must be > 0".to_string(),
63 ));
64 }
65 Ok(())
66 }
67}
68
69impl std::fmt::Debug for RecipientListConfig {
70 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
71 f.debug_struct("RecipientListConfig")
72 .field("delimiter", &self.delimiter)
73 .field("parallel", &self.parallel)
74 .field("parallel_limit", &self.parallel_limit)
75 .field("stop_on_exception", &self.stop_on_exception)
76 .finish()
77 }
78}
79
80#[cfg(test)]
81mod tests {
82 use std::sync::Arc;
83
84 use super::*;
85
86 fn noop_expr() -> RecipientListExpression {
87 Arc::new(|_| String::new())
88 }
89
90 #[test]
91 fn new_has_defaults() {
92 let cfg = RecipientListConfig::new(noop_expr());
93 assert_eq!(cfg.delimiter, ",");
94 assert!(!cfg.parallel);
95 assert!(cfg.parallel_limit.is_none());
96 assert!(!cfg.stop_on_exception);
97 }
98
99 #[test]
100 fn builder_chaining() {
101 let cfg = RecipientListConfig::new(noop_expr())
102 .delimiter(";")
103 .parallel(true)
104 .parallel_limit(4)
105 .stop_on_exception(true)
106 .strategy(crate::MulticastStrategy::CollectAll);
107 assert_eq!(cfg.delimiter, ";");
108 assert!(cfg.parallel);
109 assert_eq!(cfg.parallel_limit, Some(4));
110 assert!(cfg.stop_on_exception);
111 }
112
113 #[test]
114 fn clone_preserves_values() {
115 let cfg = RecipientListConfig::new(noop_expr())
116 .delimiter("|")
117 .parallel(true);
118 let cloned = cfg.clone();
119 assert_eq!(cloned.delimiter, "|");
120 assert!(cloned.parallel);
121 }
122
123 #[test]
124 fn debug_format() {
125 let cfg = RecipientListConfig::new(noop_expr());
126 let debug = format!("{cfg:?}");
127 assert!(debug.contains("RecipientListConfig"));
128 assert!(debug.contains("delimiter"));
129 }
130}