Skip to main content

ferro_broadcast/
config.rs

1//! Configuration for the broadcast system.
2
3use std::env;
4use std::time::Duration;
5
6/// Configuration for the broadcaster.
7#[derive(Debug, Clone)]
8pub struct BroadcastConfig {
9    /// Maximum subscribers per channel (0 = unlimited).
10    pub max_subscribers_per_channel: usize,
11    /// Maximum channels (0 = unlimited).
12    pub max_channels: usize,
13    /// Heartbeat interval for WebSocket connections.
14    pub heartbeat_interval: Duration,
15    /// Client timeout (disconnect if no activity).
16    pub client_timeout: Duration,
17    /// Whether to allow client-to-client messages (whisper).
18    pub allow_client_events: bool,
19}
20
21impl Default for BroadcastConfig {
22    fn default() -> Self {
23        Self {
24            max_subscribers_per_channel: 0,
25            max_channels: 0,
26            heartbeat_interval: Duration::from_secs(30),
27            client_timeout: Duration::from_secs(60),
28            allow_client_events: true,
29        }
30    }
31}
32
33impl BroadcastConfig {
34    /// Create a new broadcast config with defaults.
35    pub fn new() -> Self {
36        Self::default()
37    }
38
39    /// Create configuration from environment variables.
40    ///
41    /// Reads the following environment variables:
42    /// - `BROADCAST_MAX_SUBSCRIBERS`: Max subscribers per channel (default: unlimited)
43    /// - `BROADCAST_MAX_CHANNELS`: Max total channels (default: unlimited)
44    /// - `BROADCAST_HEARTBEAT_INTERVAL`: Heartbeat interval in seconds (default: 30)
45    /// - `BROADCAST_CLIENT_TIMEOUT`: Client timeout in seconds (default: 60)
46    /// - `BROADCAST_ALLOW_CLIENT_EVENTS`: Allow whisper messages (default: true)
47    ///
48    /// # Example
49    ///
50    /// ```rust,ignore
51    /// use ferro_broadcast::BroadcastConfig;
52    ///
53    /// let config = BroadcastConfig::from_env();
54    /// let broadcaster = Broadcaster::with_config(config);
55    /// ```
56    pub fn from_env() -> Self {
57        Self {
58            max_subscribers_per_channel: env::var("BROADCAST_MAX_SUBSCRIBERS")
59                .ok()
60                .and_then(|v| v.parse().ok())
61                .unwrap_or(0),
62            max_channels: env::var("BROADCAST_MAX_CHANNELS")
63                .ok()
64                .and_then(|v| v.parse().ok())
65                .unwrap_or(0),
66            heartbeat_interval: Duration::from_secs(
67                env::var("BROADCAST_HEARTBEAT_INTERVAL")
68                    .ok()
69                    .and_then(|v| v.parse().ok())
70                    .unwrap_or(30),
71            ),
72            client_timeout: Duration::from_secs(
73                env::var("BROADCAST_CLIENT_TIMEOUT")
74                    .ok()
75                    .and_then(|v| v.parse().ok())
76                    .unwrap_or(60),
77            ),
78            allow_client_events: env::var("BROADCAST_ALLOW_CLIENT_EVENTS")
79                .map(|v| v.to_lowercase() != "false" && v != "0")
80                .unwrap_or(true),
81        }
82    }
83
84    /// Set maximum subscribers per channel.
85    pub fn max_subscribers_per_channel(mut self, max: usize) -> Self {
86        self.max_subscribers_per_channel = max;
87        self
88    }
89
90    /// Set maximum channels.
91    pub fn max_channels(mut self, max: usize) -> Self {
92        self.max_channels = max;
93        self
94    }
95
96    /// Set heartbeat interval.
97    pub fn heartbeat_interval(mut self, interval: Duration) -> Self {
98        self.heartbeat_interval = interval;
99        self
100    }
101
102    /// Set client timeout.
103    pub fn client_timeout(mut self, timeout: Duration) -> Self {
104        self.client_timeout = timeout;
105        self
106    }
107
108    /// Set whether client events (whisper) are allowed.
109    pub fn allow_client_events(mut self, allow: bool) -> Self {
110        self.allow_client_events = allow;
111        self
112    }
113}
114
115#[cfg(test)]
116mod tests {
117    use super::*;
118
119    #[test]
120    fn test_broadcast_config_defaults() {
121        let config = BroadcastConfig::default();
122        assert_eq!(config.max_subscribers_per_channel, 0);
123        assert_eq!(config.max_channels, 0);
124        assert_eq!(config.heartbeat_interval, Duration::from_secs(30));
125        assert_eq!(config.client_timeout, Duration::from_secs(60));
126        assert!(config.allow_client_events);
127    }
128
129    #[test]
130    fn test_broadcast_config_builder() {
131        let config = BroadcastConfig::new()
132            .max_subscribers_per_channel(100)
133            .max_channels(50)
134            .heartbeat_interval(Duration::from_secs(15))
135            .allow_client_events(false);
136
137        assert_eq!(config.max_subscribers_per_channel, 100);
138        assert_eq!(config.max_channels, 50);
139        assert_eq!(config.heartbeat_interval, Duration::from_secs(15));
140        assert!(!config.allow_client_events);
141    }
142}