1use std::time::Duration;
8
9#[derive(Debug, Clone)]
14pub struct BrokerConfig {
15 pub callback_port_range: (u16, u16),
18
19 pub event_timeout: Duration,
22
23 pub polling_activation_delay: Duration,
26
27 pub base_polling_interval: Duration,
30
31 pub max_polling_interval: Duration,
34
35 pub subscription_timeout: Duration,
38
39 pub event_buffer_size: usize,
42
43 pub max_concurrent_polls: usize,
46
47 pub enable_proactive_firewall_detection: bool,
50
51 pub firewall_event_wait_timeout: Duration,
54
55 pub enable_firewall_caching: bool,
58
59 pub max_cached_device_states: usize,
62
63 pub max_registrations: usize,
66
67 pub adaptive_polling: bool,
70
71 pub renewal_threshold: Duration,
74
75 pub force_polling_mode: bool,
79}
80
81impl Default for BrokerConfig {
82 fn default() -> Self {
83 Self {
84 callback_port_range: (3400, 3500),
85 event_timeout: Duration::from_secs(30),
86 polling_activation_delay: Duration::from_secs(5),
87 base_polling_interval: Duration::from_secs(5),
88 max_polling_interval: Duration::from_secs(30),
89 subscription_timeout: Duration::from_secs(1800), event_buffer_size: 1000,
91 max_concurrent_polls: 50,
92 enable_proactive_firewall_detection: true,
93 firewall_event_wait_timeout: Duration::from_secs(15),
94 enable_firewall_caching: true,
95 max_cached_device_states: 100,
96 max_registrations: 1000,
97 adaptive_polling: true,
98 renewal_threshold: Duration::from_secs(300), force_polling_mode: false,
100 }
101 }
102}
103
104impl BrokerConfig {
105 pub fn new() -> Self {
107 Self::default()
108 }
109
110 pub fn fast_polling() -> Self {
112 Self {
113 base_polling_interval: Duration::from_secs(2),
114 max_polling_interval: Duration::from_secs(10),
115 polling_activation_delay: Duration::from_secs(1),
116 event_timeout: Duration::from_secs(15),
117 firewall_event_wait_timeout: Duration::from_secs(5), ..Default::default()
119 }
120 }
121
122 pub fn resource_efficient() -> Self {
124 Self {
125 base_polling_interval: Duration::from_secs(10),
126 max_polling_interval: Duration::from_secs(60),
127 event_buffer_size: 100,
128 max_concurrent_polls: 10,
129 max_registrations: 100,
130 max_cached_device_states: 50, ..Default::default()
132 }
133 }
134
135 pub fn no_firewall_detection() -> Self {
137 Self {
138 enable_proactive_firewall_detection: false,
139 ..Default::default()
140 }
141 }
142
143 pub fn firewall_simulation() -> Self {
146 Self {
147 force_polling_mode: true,
148 base_polling_interval: Duration::from_secs(2),
149 max_polling_interval: Duration::from_secs(10),
150 ..Default::default()
151 }
152 }
153
154 pub fn validate(&self) -> Result<(), crate::BrokerError> {
156 if self.callback_port_range.0 >= self.callback_port_range.1 {
157 return Err(crate::BrokerError::Configuration(
158 "Invalid callback port range: start must be less than end".to_string(),
159 ));
160 }
161
162 if self.base_polling_interval >= self.max_polling_interval {
163 return Err(crate::BrokerError::Configuration(
164 "Invalid polling interval: base must be less than max".to_string(),
165 ));
166 }
167
168 if self.event_buffer_size == 0 {
169 return Err(crate::BrokerError::Configuration(
170 "Event buffer size must be greater than 0".to_string(),
171 ));
172 }
173
174 if self.max_concurrent_polls == 0 {
175 return Err(crate::BrokerError::Configuration(
176 "Max concurrent polls must be greater than 0".to_string(),
177 ));
178 }
179
180 if self.max_registrations == 0 {
181 return Err(crate::BrokerError::Configuration(
182 "Max registrations must be greater than 0".to_string(),
183 ));
184 }
185
186 if self.max_cached_device_states == 0 {
187 return Err(crate::BrokerError::Configuration(
188 "Max cached device states must be greater than 0".to_string(),
189 ));
190 }
191
192 if self.firewall_event_wait_timeout == Duration::ZERO {
193 return Err(crate::BrokerError::Configuration(
194 "Firewall event wait timeout must be greater than 0".to_string(),
195 ));
196 }
197
198 Ok(())
199 }
200
201 pub fn with_callback_ports(mut self, start: u16, end: u16) -> Self {
203 self.callback_port_range = (start, end);
204 self
205 }
206
207 pub fn with_polling_interval(mut self, base: Duration, max: Duration) -> Self {
208 self.base_polling_interval = base;
209 self.max_polling_interval = max;
210 self
211 }
212
213 pub fn with_event_timeout(mut self, timeout: Duration) -> Self {
214 self.event_timeout = timeout;
215 self
216 }
217
218 pub fn with_buffer_size(mut self, size: usize) -> Self {
219 self.event_buffer_size = size;
220 self
221 }
222
223 pub fn with_firewall_detection(mut self, enabled: bool) -> Self {
224 self.enable_proactive_firewall_detection = enabled;
225 self
226 }
227
228 pub fn with_force_polling(mut self, enabled: bool) -> Self {
229 self.force_polling_mode = enabled;
230 self
231 }
232}
233
234#[cfg(test)]
235mod tests {
236 use super::*;
237
238 #[test]
239 fn test_default_config() {
240 let config = BrokerConfig::default();
241 assert_eq!(config.callback_port_range, (3400, 3500));
242 assert_eq!(config.event_timeout, Duration::from_secs(30));
243 assert!(config.enable_proactive_firewall_detection);
244 assert!(!config.force_polling_mode);
245 assert!(config.validate().is_ok());
246 }
247
248 #[test]
249 fn test_config_validation() {
250 let invalid_config = BrokerConfig {
251 callback_port_range: (3500, 3400), ..Default::default()
253 };
254 assert!(invalid_config.validate().is_err());
255
256 let invalid_polling = BrokerConfig {
257 base_polling_interval: Duration::from_secs(30),
258 max_polling_interval: Duration::from_secs(10), ..Default::default()
260 };
261 assert!(invalid_polling.validate().is_err());
262 }
263
264 #[test]
265 fn test_config_presets() {
266 let fast = BrokerConfig::fast_polling();
267 assert_eq!(fast.base_polling_interval, Duration::from_secs(2));
268 assert!(fast.validate().is_ok());
269
270 let efficient = BrokerConfig::resource_efficient();
271 assert_eq!(efficient.max_concurrent_polls, 10);
272 assert!(efficient.validate().is_ok());
273
274 let no_fw = BrokerConfig::no_firewall_detection();
275 assert!(!no_fw.enable_proactive_firewall_detection);
276 assert!(no_fw.validate().is_ok());
277
278 let fw_sim = BrokerConfig::firewall_simulation();
279 assert!(fw_sim.force_polling_mode);
280 assert_eq!(fw_sim.base_polling_interval, Duration::from_secs(2));
281 assert!(fw_sim.validate().is_ok());
282 }
283
284 #[test]
285 fn test_builder_pattern() {
286 let config = BrokerConfig::new()
287 .with_callback_ports(4000, 4100)
288 .with_polling_interval(Duration::from_secs(3), Duration::from_secs(15))
289 .with_event_timeout(Duration::from_secs(45))
290 .with_buffer_size(2000)
291 .with_firewall_detection(false);
292
293 assert_eq!(config.callback_port_range, (4000, 4100));
294 assert_eq!(config.base_polling_interval, Duration::from_secs(3));
295 assert_eq!(config.event_buffer_size, 2000);
296 assert!(!config.enable_proactive_firewall_detection);
297 assert!(config.validate().is_ok());
298 }
299}