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 super::Types::ConnectionHandle;
35use crate::dev_log;
36
37/// Connection health checker
38///
39/// This structure provides periodic health checking for connections,
40/// monitoring response times and overall connection health.
41///
42/// ## Health Check Process
43///
44/// ```text
45/// Connection
46/// |
47/// | 1. Send ping
48/// v
49/// Measure response time
50/// |
51/// | 2. Compare to timeout
52/// v
53/// Health decision (healthy/unhealthy)
54/// ```
55///
56/// ## Health Criteria
57///
58/// A connection is considered healthy if:
59/// - Response time < ping_timeout (default 5 seconds)
60///
61/// ## Example Usage
62///
63/// ```rust,ignore
64/// let checker = HealthChecker::new();
65/// let mut handle = ConnectionHandle::new();
66///
67/// let is_healthy = checker.check_connection_health(&mut handle).await;
68/// ```
69pub struct HealthChecker {
70 /// Maximum allowed response time for a connection to be considered healthy
71 ping_timeout:std::time::Duration,
72}
73
74impl HealthChecker {
75 /// Create a new health checker with default settings
76 ///
77 /// Default ping timeout is 5 seconds.
78 pub fn new() -> Self {
79 dev_log!("ipc", "[HealthChecker] Creating health checker with 5s timeout");
80
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 dev_log!("ipc", "[HealthChecker] Creating health checker with {:?} timeout", ping_timeout);
90
91 Self { ping_timeout }
92 }
93
94 /// Check connection health by sending a ping
95 ///
96 /// This method simulates a health check by measuring response time.
97 /// In a production environment, this would send an actual ping message
98 /// through the connection.
99 ///
100 /// ## Parameters
101 /// - `handle`: Mutable reference to the connection handle to update based
102 /// on health
103 ///
104 /// ## Returns
105 /// - `true`: Connection is healthy
106 /// - `false`: Connection is unhealthy
107 ///
108 /// ## Example
109 ///
110 /// ```rust,ignore
111 /// let is_healthy = checker.check_connection_health(&mut handle).await;
112 /// ```
113 pub async fn check_connection_health(&self, handle:&mut ConnectionHandle) -> bool {
114 let start_time = std::time::Instant::now();
115
116 // Simulate network latency (in production, this would be an actual ping)
117 // Using a small delay to simulate realistic network conditions
118 tokio::time::sleep(std::time::Duration::from_millis(10)).await;
119
120 let response_time = start_time.elapsed();
121
122 // Connection is healthy if response time is within timeout
123 let is_healthy = response_time < self.ping_timeout;
124
125 if is_healthy {
126 dev_log!(
127 "ipc",
128 "[HealthChecker] Connection {} is healthy (response time: {:?})",
129 handle.id,
130 response_time
131 );
132 } else {
133 dev_log!(
134 "ipc",
135 "[HealthChecker] Connection {} is unhealthy (response time: {:?}, timeout: {:?})",
136 handle.id,
137 response_time,
138 self.ping_timeout
139 );
140 }
141
142 is_healthy
143 }
144
145 /// Get the ping timeout
146 pub fn ping_timeout(&self) -> std::time::Duration { self.ping_timeout }
147
148 /// Set a new ping timeout
149 pub fn set_ping_timeout(&mut self, timeout:std::time::Duration) {
150 self.ping_timeout = timeout;
151
152 dev_log!("ipc", "[HealthChecker] Ping timeout updated to {:?}", timeout);
153 }
154}
155
156impl Default for HealthChecker {
157 fn default() -> Self { Self::new() }
158}
159
160#[cfg(test)]
161mod tests {
162
163 use super::*;
164
165 #[tokio::test]
166 async fn test_health_checker_creation() {
167 let checker = HealthChecker::new();
168
169 assert_eq!(checker.ping_timeout, std::time::Duration::from_secs(5));
170 }
171
172 #[tokio::test]
173 async fn test_health_checker_custom_timeout() {
174 let timeout = std::time::Duration::from_secs(10);
175
176 let checker = HealthChecker::with_timeout(timeout);
177
178 assert_eq!(checker.ping_timeout, timeout);
179 }
180
181 #[tokio::test]
182 async fn test_check_connection_health_healthy() {
183 let checker = HealthChecker::new();
184
185 let mut handle = ConnectionHandle::new();
186
187 let is_healthy = checker.check_connection_health(&mut handle).await;
188
189 assert!(is_healthy);
190 }
191
192 #[tokio::test]
193 async fn test_check_connection_health_unhealthy() {
194 // Create a checker with very short timeout
195 let timeout = std::time::Duration::from_millis(1);
196
197 let checker = HealthChecker::with_timeout(timeout);
198
199 let mut handle = ConnectionHandle::new();
200
201 // The simulated latency (10ms) should exceed the timeout (1ms)
202 let is_healthy = checker.check_connection_health(&mut handle).await;
203
204 assert!(!is_healthy);
205 }
206
207 #[test]
208 fn test_default_health_checker() {
209 let checker = HealthChecker::default();
210
211 assert_eq!(checker.ping_timeout, std::time::Duration::from_secs(5));
212 }
213
214 #[test]
215 fn test_set_ping_timeout() {
216 let mut checker = HealthChecker::new();
217
218 assert_eq!(checker.ping_timeout, std::time::Duration::from_secs(5));
219
220 let new_timeout = std::time::Duration::from_secs(15);
221
222 checker.set_ping_timeout(new_timeout);
223
224 assert_eq!(checker.ping_timeout, new_timeout);
225 }
226}