use std::time::Duration;
#[derive(Debug, Clone)]
pub struct BrokerConfig {
pub callback_port_range: (u16, u16),
pub event_timeout: Duration,
pub polling_activation_delay: Duration,
pub base_polling_interval: Duration,
pub max_polling_interval: Duration,
pub subscription_timeout: Duration,
pub event_buffer_size: usize,
pub max_concurrent_polls: usize,
pub enable_proactive_firewall_detection: bool,
pub firewall_event_wait_timeout: Duration,
pub enable_firewall_caching: bool,
pub max_cached_device_states: usize,
pub max_registrations: usize,
pub adaptive_polling: bool,
pub renewal_threshold: Duration,
pub force_polling_mode: bool,
}
impl Default for BrokerConfig {
fn default() -> Self {
Self {
callback_port_range: (3400, 3500),
event_timeout: Duration::from_secs(30),
polling_activation_delay: Duration::from_secs(5),
base_polling_interval: Duration::from_secs(5),
max_polling_interval: Duration::from_secs(30),
subscription_timeout: Duration::from_secs(1800), event_buffer_size: 1000,
max_concurrent_polls: 50,
enable_proactive_firewall_detection: true,
firewall_event_wait_timeout: Duration::from_secs(15),
enable_firewall_caching: true,
max_cached_device_states: 100,
max_registrations: 1000,
adaptive_polling: true,
renewal_threshold: Duration::from_secs(300), force_polling_mode: false,
}
}
}
impl BrokerConfig {
pub fn new() -> Self {
Self::default()
}
pub fn fast_polling() -> Self {
Self {
base_polling_interval: Duration::from_secs(2),
max_polling_interval: Duration::from_secs(10),
polling_activation_delay: Duration::from_secs(1),
event_timeout: Duration::from_secs(15),
firewall_event_wait_timeout: Duration::from_secs(5), ..Default::default()
}
}
pub fn resource_efficient() -> Self {
Self {
base_polling_interval: Duration::from_secs(10),
max_polling_interval: Duration::from_secs(60),
event_buffer_size: 100,
max_concurrent_polls: 10,
max_registrations: 100,
max_cached_device_states: 50, ..Default::default()
}
}
pub fn no_firewall_detection() -> Self {
Self {
enable_proactive_firewall_detection: false,
..Default::default()
}
}
pub fn firewall_simulation() -> Self {
Self {
force_polling_mode: true,
base_polling_interval: Duration::from_secs(2),
max_polling_interval: Duration::from_secs(10),
..Default::default()
}
}
pub fn validate(&self) -> Result<(), crate::BrokerError> {
if self.callback_port_range.0 >= self.callback_port_range.1 {
return Err(crate::BrokerError::Configuration(
"Invalid callback port range: start must be less than end".to_string(),
));
}
if self.base_polling_interval >= self.max_polling_interval {
return Err(crate::BrokerError::Configuration(
"Invalid polling interval: base must be less than max".to_string(),
));
}
if self.event_buffer_size == 0 {
return Err(crate::BrokerError::Configuration(
"Event buffer size must be greater than 0".to_string(),
));
}
if self.max_concurrent_polls == 0 {
return Err(crate::BrokerError::Configuration(
"Max concurrent polls must be greater than 0".to_string(),
));
}
if self.max_registrations == 0 {
return Err(crate::BrokerError::Configuration(
"Max registrations must be greater than 0".to_string(),
));
}
if self.max_cached_device_states == 0 {
return Err(crate::BrokerError::Configuration(
"Max cached device states must be greater than 0".to_string(),
));
}
if self.firewall_event_wait_timeout == Duration::ZERO {
return Err(crate::BrokerError::Configuration(
"Firewall event wait timeout must be greater than 0".to_string(),
));
}
Ok(())
}
pub fn with_callback_ports(mut self, start: u16, end: u16) -> Self {
self.callback_port_range = (start, end);
self
}
pub fn with_polling_interval(mut self, base: Duration, max: Duration) -> Self {
self.base_polling_interval = base;
self.max_polling_interval = max;
self
}
pub fn with_event_timeout(mut self, timeout: Duration) -> Self {
self.event_timeout = timeout;
self
}
pub fn with_buffer_size(mut self, size: usize) -> Self {
self.event_buffer_size = size;
self
}
pub fn with_firewall_detection(mut self, enabled: bool) -> Self {
self.enable_proactive_firewall_detection = enabled;
self
}
pub fn with_force_polling(mut self, enabled: bool) -> Self {
self.force_polling_mode = enabled;
self
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_config() {
let config = BrokerConfig::default();
assert_eq!(config.callback_port_range, (3400, 3500));
assert_eq!(config.event_timeout, Duration::from_secs(30));
assert!(config.enable_proactive_firewall_detection);
assert!(!config.force_polling_mode);
assert!(config.validate().is_ok());
}
#[test]
fn test_config_validation() {
let invalid_config = BrokerConfig {
callback_port_range: (3500, 3400), ..Default::default()
};
assert!(invalid_config.validate().is_err());
let invalid_polling = BrokerConfig {
base_polling_interval: Duration::from_secs(30),
max_polling_interval: Duration::from_secs(10), ..Default::default()
};
assert!(invalid_polling.validate().is_err());
}
#[test]
fn test_config_presets() {
let fast = BrokerConfig::fast_polling();
assert_eq!(fast.base_polling_interval, Duration::from_secs(2));
assert!(fast.validate().is_ok());
let efficient = BrokerConfig::resource_efficient();
assert_eq!(efficient.max_concurrent_polls, 10);
assert!(efficient.validate().is_ok());
let no_fw = BrokerConfig::no_firewall_detection();
assert!(!no_fw.enable_proactive_firewall_detection);
assert!(no_fw.validate().is_ok());
let fw_sim = BrokerConfig::firewall_simulation();
assert!(fw_sim.force_polling_mode);
assert_eq!(fw_sim.base_polling_interval, Duration::from_secs(2));
assert!(fw_sim.validate().is_ok());
}
#[test]
fn test_builder_pattern() {
let config = BrokerConfig::new()
.with_callback_ports(4000, 4100)
.with_polling_interval(Duration::from_secs(3), Duration::from_secs(15))
.with_event_timeout(Duration::from_secs(45))
.with_buffer_size(2000)
.with_firewall_detection(false);
assert_eq!(config.callback_port_range, (4000, 4100));
assert_eq!(config.base_polling_interval, Duration::from_secs(3));
assert_eq!(config.event_buffer_size, 2000);
assert!(!config.enable_proactive_firewall_detection);
assert!(config.validate().is_ok());
}
}