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}