Mountain/IPC/Connection/Health.rs
1//! # Health Checker (IPC Connection)
2//!
3//! ## RESPONSIBILITIES
4//! This module provides connection health checking functionality for the
5//! IPC layer. It monitors connection health through periodic checks and
6//! provides metrics for debugging and monitoring.
7//!
8//! ## ARCHITECTURAL ROLE
9//! This module is part of the monitoring subsystem in the connection management
10//! layer, providing health assessments for active connections.
11//!
12//! ## KEY COMPONENTS
13//!
14//! - **HealthChecker**: Periodic connection health monitoring
15//!
16//! ## ERROR HANDLING
17// Health checks return boolean results indicating health status.
18//
19// ## LOGGING
20// Debug-level logging for health check results.
21//
22// ## Performance Considerations
23// - Health checks run in background tasks
24// - Non-blocking implementation using Tokio
25// - Configurable check intervals
26// - Timeout-based health assessment
27//
28// ## TODO
29// - Add configurable health check strategies
30// - Implement health check customization
31// - Add health history tracking
32// - Support multiple health check types
33
34use log::debug;
35
36use super::Types::ConnectionHandle;
37
38/// Connection health checker
39///
40/// This structure provides periodic health checking for connections,
41/// monitoring response times and overall connection health.
42///
43/// ## Health Check Process
44///
45/// ```text
46/// Connection
47/// |
48/// | 1. Send ping
49/// v
50/// Measure response time
51/// |
52/// | 2. Compare to timeout
53/// v
54/// Health decision (healthy/unhealthy)
55/// ```
56///
57/// ## Health Criteria
58///
59/// A connection is considered healthy if:
60/// - Response time < ping_timeout (default 5 seconds)
61///
62/// ## Example Usage
63///
64/// ```rust,ignore
65/// let checker = HealthChecker::new();
66/// let mut handle = ConnectionHandle::new();
67///
68/// let is_healthy = checker.check_connection_health(&mut handle).await;
69/// ```
70pub struct HealthChecker {
71 /// Maximum allowed response time for a connection to be considered healthy
72 ping_timeout:std::time::Duration,
73}
74
75impl HealthChecker {
76 /// Create a new health checker with default settings
77 ///
78 /// Default ping timeout is 5 seconds.
79 pub fn new() -> Self {
80 debug!("[HealthChecker] Creating health checker with 5s timeout");
81 Self { ping_timeout:std::time::Duration::from_secs(5) }
82 }
83
84 /// Create a new health checker with custom timeout
85 ///
86 /// ## Parameters
87 /// - `ping_timeout`: Maximum allowed response time
88 pub fn with_timeout(ping_timeout:std::time::Duration) -> Self {
89 debug!("[HealthChecker] Creating health checker with {:?} timeout", ping_timeout);
90 Self { ping_timeout }
91 }
92
93 /// Check connection health by sending a ping
94 ///
95 /// This method simulates a health check by measuring response time.
96 /// In a production environment, this would send an actual ping message
97 /// through the connection.
98 ///
99 /// ## Parameters
100 /// - `handle`: Mutable reference to the connection handle to update based
101 /// on health
102 ///
103 /// ## Returns
104 /// - `true`: Connection is healthy
105 /// - `false`: Connection is unhealthy
106 ///
107 /// ## Example
108 ///
109 /// ```rust,ignore
110 /// let is_healthy = checker.check_connection_health(&mut handle).await;
111 /// ```
112 pub async fn check_connection_health(&self, handle:&mut ConnectionHandle) -> bool {
113 let start_time = std::time::Instant::now();
114
115 // Simulate network latency (in production, this would be an actual ping)
116 // Using a small delay to simulate realistic network conditions
117 tokio::time::sleep(std::time::Duration::from_millis(10)).await;
118
119 let response_time = start_time.elapsed();
120
121 // Connection is healthy if response time is within timeout
122 let is_healthy = response_time < self.ping_timeout;
123
124 if is_healthy {
125 debug!(
126 "[HealthChecker] Connection {} is healthy (response time: {:?})",
127 handle.id, response_time
128 );
129 } else {
130 debug!(
131 "[HealthChecker] Connection {} is unhealthy (response time: {:?}, timeout: {:?})",
132 handle.id, response_time, self.ping_timeout
133 );
134 }
135
136 is_healthy
137 }
138
139 /// Get the ping timeout
140 pub fn ping_timeout(&self) -> std::time::Duration { self.ping_timeout }
141
142 /// Set a new ping timeout
143 pub fn set_ping_timeout(&mut self, timeout:std::time::Duration) {
144 self.ping_timeout = timeout;
145 debug!("[HealthChecker] Ping timeout updated to {:?}", timeout);
146 }
147}
148
149impl Default for HealthChecker {
150 fn default() -> Self { Self::new() }
151}
152
153#[cfg(test)]
154mod tests {
155 use super::*;
156
157 #[tokio::test]
158 async fn test_health_checker_creation() {
159 let checker = HealthChecker::new();
160 assert_eq!(checker.ping_timeout, std::time::Duration::from_secs(5));
161 }
162
163 #[tokio::test]
164 async fn test_health_checker_custom_timeout() {
165 let timeout = std::time::Duration::from_secs(10);
166 let checker = HealthChecker::with_timeout(timeout);
167 assert_eq!(checker.ping_timeout, timeout);
168 }
169
170 #[tokio::test]
171 async fn test_check_connection_health_healthy() {
172 let checker = HealthChecker::new();
173 let mut handle = ConnectionHandle::new();
174
175 let is_healthy = checker.check_connection_health(&mut handle).await;
176 assert!(is_healthy);
177 }
178
179 #[tokio::test]
180 async fn test_check_connection_health_unhealthy() {
181 // Create a checker with very short timeout
182 let timeout = std::time::Duration::from_millis(1);
183 let checker = HealthChecker::with_timeout(timeout);
184 let mut handle = ConnectionHandle::new();
185
186 // The simulated latency (10ms) should exceed the timeout (1ms)
187 let is_healthy = checker.check_connection_health(&mut handle).await;
188 assert!(!is_healthy);
189 }
190
191 #[test]
192 fn test_default_health_checker() {
193 let checker = HealthChecker::default();
194 assert_eq!(checker.ping_timeout, std::time::Duration::from_secs(5));
195 }
196
197 #[test]
198 fn test_set_ping_timeout() {
199 let mut checker = HealthChecker::new();
200 assert_eq!(checker.ping_timeout, std::time::Duration::from_secs(5));
201
202 let new_timeout = std::time::Duration::from_secs(15);
203 checker.set_ping_timeout(new_timeout);
204 assert_eq!(checker.ping_timeout, new_timeout);
205 }
206}