Skip to main content

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}