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 Self { ping_timeout:std::time::Duration::from_secs(5) }
81 }
82
83 /// Create a new health checker with custom timeout
84 ///
85 /// ## Parameters
86 /// - `ping_timeout`: Maximum allowed response time
87 pub fn with_timeout(ping_timeout:std::time::Duration) -> Self {
88 dev_log!("ipc", "[HealthChecker] Creating health checker with {:?} timeout", ping_timeout);
89 Self { ping_timeout }
90 }
91
92 /// Check connection health by sending a ping
93 ///
94 /// This method simulates a health check by measuring response time.
95 /// In a production environment, this would send an actual ping message
96 /// through the connection.
97 ///
98 /// ## Parameters
99 /// - `handle`: Mutable reference to the connection handle to update based
100 /// on health
101 ///
102 /// ## Returns
103 /// - `true`: Connection is healthy
104 /// - `false`: Connection is unhealthy
105 ///
106 /// ## Example
107 ///
108 /// ```rust,ignore
109 /// let is_healthy = checker.check_connection_health(&mut handle).await;
110 /// ```
111 pub async fn check_connection_health(&self, handle:&mut ConnectionHandle) -> bool {
112 let start_time = std::time::Instant::now();
113
114 // Simulate network latency (in production, this would be an actual ping)
115 // Using a small delay to simulate realistic network conditions
116 tokio::time::sleep(std::time::Duration::from_millis(10)).await;
117
118 let response_time = start_time.elapsed();
119
120 // Connection is healthy if response time is within timeout
121 let is_healthy = response_time < self.ping_timeout;
122
123 if is_healthy {
124 dev_log!(
125 "ipc",
126 "[HealthChecker] Connection {} is healthy (response time: {:?})",
127 handle.id,
128 response_time
129 );
130 } else {
131 dev_log!(
132 "ipc",
133 "[HealthChecker] Connection {} is unhealthy (response time: {:?}, timeout: {:?})",
134 handle.id,
135 response_time,
136 self.ping_timeout
137 );
138 }
139
140 is_healthy
141 }
142
143 /// Get the ping timeout
144 pub fn ping_timeout(&self) -> std::time::Duration { self.ping_timeout }
145
146 /// Set a new ping timeout
147 pub fn set_ping_timeout(&mut self, timeout:std::time::Duration) {
148 self.ping_timeout = timeout;
149 dev_log!("ipc", "[HealthChecker] Ping timeout updated to {:?}", timeout);
150 }
151}
152
153impl Default for HealthChecker {
154 fn default() -> Self { Self::new() }
155}
156
157#[cfg(test)]
158mod tests {
159 use super::*;
160
161 #[tokio::test]
162 async fn test_health_checker_creation() {
163 let checker = HealthChecker::new();
164 assert_eq!(checker.ping_timeout, std::time::Duration::from_secs(5));
165 }
166
167 #[tokio::test]
168 async fn test_health_checker_custom_timeout() {
169 let timeout = std::time::Duration::from_secs(10);
170 let checker = HealthChecker::with_timeout(timeout);
171 assert_eq!(checker.ping_timeout, timeout);
172 }
173
174 #[tokio::test]
175 async fn test_check_connection_health_healthy() {
176 let checker = HealthChecker::new();
177 let mut handle = ConnectionHandle::new();
178
179 let is_healthy = checker.check_connection_health(&mut handle).await;
180 assert!(is_healthy);
181 }
182
183 #[tokio::test]
184 async fn test_check_connection_health_unhealthy() {
185 // Create a checker with very short timeout
186 let timeout = std::time::Duration::from_millis(1);
187 let checker = HealthChecker::with_timeout(timeout);
188 let mut handle = ConnectionHandle::new();
189
190 // The simulated latency (10ms) should exceed the timeout (1ms)
191 let is_healthy = checker.check_connection_health(&mut handle).await;
192 assert!(!is_healthy);
193 }
194
195 #[test]
196 fn test_default_health_checker() {
197 let checker = HealthChecker::default();
198 assert_eq!(checker.ping_timeout, std::time::Duration::from_secs(5));
199 }
200
201 #[test]
202 fn test_set_ping_timeout() {
203 let mut checker = HealthChecker::new();
204 assert_eq!(checker.ping_timeout, std::time::Duration::from_secs(5));
205
206 let new_timeout = std::time::Duration::from_secs(15);
207 checker.set_ping_timeout(new_timeout);
208 assert_eq!(checker.ping_timeout, new_timeout);
209 }
210}