Skip to main content

canlink_hal/monitor/
connection.rs

1//! Connection monitor implementation (FR-010)
2//!
3//! Provides connection state monitoring with optional auto-reconnect.
4
5use std::time::Duration;
6
7use super::{ConnectionState, ReconnectConfig};
8
9/// Connection monitor
10///
11/// Monitors backend connection state and optionally handles automatic
12/// reconnection. By default, auto-reconnect is disabled.
13///
14/// # Example
15///
16/// ```rust,ignore
17/// use canlink_hal::monitor::{ConnectionMonitor, ConnectionState};
18/// use std::time::Duration;
19///
20/// let monitor = ConnectionMonitor::new(Duration::from_secs(1));
21/// ```
22pub struct ConnectionMonitor {
23    /// Heartbeat interval
24    heartbeat_interval: Duration,
25    /// Reconnect configuration (None = disabled)
26    reconnect_config: Option<ReconnectConfig>,
27    /// Current connection state
28    state: ConnectionState,
29}
30
31impl ConnectionMonitor {
32    /// Create a new connection monitor without auto-reconnect
33    ///
34    /// # Arguments
35    ///
36    /// * `heartbeat_interval` - Interval between heartbeat checks
37    #[must_use]
38    pub fn new(heartbeat_interval: Duration) -> Self {
39        Self {
40            heartbeat_interval,
41            reconnect_config: None,
42            state: ConnectionState::Connected,
43        }
44    }
45
46    /// Create a connection monitor with auto-reconnect enabled
47    ///
48    /// # Arguments
49    ///
50    /// * `heartbeat_interval` - Interval between heartbeat checks
51    /// * `reconnect_config` - Reconnection configuration
52    #[must_use]
53    pub fn with_reconnect(heartbeat_interval: Duration, reconnect_config: ReconnectConfig) -> Self {
54        Self {
55            heartbeat_interval,
56            reconnect_config: Some(reconnect_config),
57            state: ConnectionState::Connected,
58        }
59    }
60
61    /// Get the current connection state
62    #[must_use]
63    pub fn state(&self) -> ConnectionState {
64        self.state
65    }
66
67    /// Get the heartbeat interval
68    #[must_use]
69    pub fn heartbeat_interval(&self) -> Duration {
70        self.heartbeat_interval
71    }
72
73    /// Check if auto-reconnect is enabled
74    #[must_use]
75    pub fn auto_reconnect_enabled(&self) -> bool {
76        self.reconnect_config.is_some()
77    }
78
79    /// Get the reconnect configuration
80    #[must_use]
81    pub fn reconnect_config(&self) -> Option<&ReconnectConfig> {
82        self.reconnect_config.as_ref()
83    }
84
85    /// Set the connection state (for testing/manual control)
86    pub fn set_state(&mut self, state: ConnectionState) {
87        self.state = state;
88    }
89}
90
91impl Default for ConnectionMonitor {
92    fn default() -> Self {
93        Self::new(Duration::from_secs(1))
94    }
95}
96
97#[cfg(test)]
98mod tests {
99    use super::*;
100
101    #[test]
102    fn test_new_monitor() {
103        let monitor = ConnectionMonitor::new(Duration::from_secs(1));
104        assert_eq!(monitor.state(), ConnectionState::Connected);
105        assert!(!monitor.auto_reconnect_enabled());
106    }
107
108    #[test]
109    fn test_with_reconnect() {
110        let monitor =
111            ConnectionMonitor::with_reconnect(Duration::from_secs(1), ReconnectConfig::default());
112        assert!(monitor.auto_reconnect_enabled());
113    }
114
115    #[test]
116    fn test_set_state() {
117        let mut monitor = ConnectionMonitor::new(Duration::from_secs(1));
118        monitor.set_state(ConnectionState::Disconnected);
119        assert_eq!(monitor.state(), ConnectionState::Disconnected);
120    }
121}