Skip to main content

ws_kit/
config.rs

1//! Configuration for WebSocket infrastructure.
2//!
3//! [`WsConfig`] controls heartbeat cadence, broadcast buffering, and global
4//! connection limits. Use the builder for ergonomic construction.
5
6use std::time::Duration;
7
8/// Configuration for WebSocket connections and broadcast channels.
9///
10/// # Example
11///
12/// ```
13/// use ws_kit::config::WsConfig;
14/// use std::time::Duration;
15///
16/// let cfg = WsConfig::builder()
17///     .heartbeat_interval(Duration::from_secs(15))
18///     .broadcast_capacity(2048)
19///     .max_connections(5000)
20///     .build();
21/// assert_eq!(cfg.heartbeat_interval, Duration::from_secs(15));
22/// ```
23#[derive(Debug, Clone, PartialEq, Eq)]
24pub struct WsConfig {
25    /// Interval between heartbeat pings.
26    pub heartbeat_interval: Duration,
27    /// Capacity of each broadcast channel.
28    pub broadcast_capacity: usize,
29    /// Maximum concurrent connections allowed (0 = unlimited).
30    pub max_connections: usize,
31}
32
33impl Default for WsConfig {
34    fn default() -> Self {
35        Self {
36            heartbeat_interval: Duration::from_secs(30),
37            broadcast_capacity: 1024,
38            max_connections: 1000,
39        }
40    }
41}
42
43impl WsConfig {
44    /// Create a new config with defaults.
45    pub fn new() -> Self {
46        Self::default()
47    }
48
49    /// Create a builder for [`WsConfig`].
50    pub fn builder() -> WsConfigBuilder {
51        WsConfigBuilder::default()
52    }
53}
54
55/// Builder for [`WsConfig`].
56#[derive(Debug, Clone)]
57pub struct WsConfigBuilder {
58    heartbeat_interval: Duration,
59    broadcast_capacity: usize,
60    max_connections: usize,
61}
62
63impl Default for WsConfigBuilder {
64    fn default() -> Self {
65        let d = WsConfig::default();
66        Self {
67            heartbeat_interval: d.heartbeat_interval,
68            broadcast_capacity: d.broadcast_capacity,
69            max_connections: d.max_connections,
70        }
71    }
72}
73
74impl WsConfigBuilder {
75    /// Set heartbeat interval.
76    pub fn heartbeat_interval(mut self, v: Duration) -> Self {
77        self.heartbeat_interval = v;
78        self
79    }
80
81    /// Set broadcast channel capacity.
82    pub fn broadcast_capacity(mut self, v: usize) -> Self {
83        self.broadcast_capacity = v;
84        self
85    }
86
87    /// Set maximum connection limit.
88    pub fn max_connections(mut self, v: usize) -> Self {
89        self.max_connections = v;
90        self
91    }
92
93    /// Build the [`WsConfig`].
94    pub fn build(self) -> WsConfig {
95        WsConfig {
96            heartbeat_interval: self.heartbeat_interval,
97            broadcast_capacity: self.broadcast_capacity,
98            max_connections: self.max_connections,
99        }
100    }
101}
102
103// Tests exercise failure paths and invariants directly; unwrap/expect,
104// slicing, and panicking asserts are acceptable here — violations
105// surface as test failures, not production panics.
106#[allow(
107    clippy::unwrap_used,
108    clippy::expect_used,
109    clippy::indexing_slicing,
110    clippy::panic
111)]
112#[cfg(test)]
113mod tests {
114    use super::*;
115
116    #[test]
117    fn defaults() {
118        let c = WsConfig::default();
119        assert_eq!(c.heartbeat_interval, Duration::from_secs(30));
120        assert_eq!(c.broadcast_capacity, 1024);
121        assert_eq!(c.max_connections, 1000);
122    }
123
124    #[test]
125    fn builder_overrides() {
126        let c = WsConfig::builder()
127            .heartbeat_interval(Duration::from_secs(10))
128            .broadcast_capacity(512)
129            .max_connections(10)
130            .build();
131        assert_eq!(c.heartbeat_interval, Duration::from_secs(10));
132        assert_eq!(c.broadcast_capacity, 512);
133        assert_eq!(c.max_connections, 10);
134    }
135
136    #[test]
137    fn builder_default_equals_config_default() {
138        let via_builder = WsConfig::builder().build();
139        assert_eq!(via_builder, WsConfig::default());
140    }
141}