Skip to main content

Mountain/IPC/Common/
ConnectionStatus.rs

1//! # Connection Status Tracking
2//!
3//! Provides types for tracking IPC connection health and state.
4//! Used across all IPC components to monitor connection status.
5
6use std::time::{Duration, Instant};
7
8use serde::{Deserialize, Serialize};
9
10/// Represents the current state of an IPC connection
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
12pub enum ConnectionState {
13	/// Connection is active and healthy
14	Connected,
15
16	/// Connection is being established
17	Connecting,
18
19	/// Connection is temporarily unavailable
20	Disconnected,
21
22	/// Connection has failed and needs recovery
23	Failed,
24
25	/// Connection is being closed gracefully
26	Closing,
27
28	/// Connection is closed and will not reopen
29	Closed,
30}
31
32/// Comprehensive connection status tracking
33#[derive(Debug, Clone, Serialize)]
34pub struct ConnectionStatus {
35	/// Current connection state
36	pub state:ConnectionState,
37
38	/// When the connection entered its current state (skipped for serialization
39	/// as Instant is not serializable)
40	#[serde(skip)]
41	pub state_since:Instant,
42
43	/// Count of connection attempts
44	pub connection_attempts:u32,
45
46	/// Timestamp of last successful connection (skipped for serialization as
47	/// Instant is not serializable)
48	#[serde(skip)]
49	pub last_connected:Option<Instant>,
50
51	/// Timestamp of last disconnection (skipped for serialization as Instant is
52	/// not serializable)
53	#[serde(skip)]
54	pub last_disconnected:Option<Instant>,
55
56	/// Total uptime duration
57	pub total_uptime:Duration,
58
59	/// Reason for last disconnection (if any)
60	pub last_error:Option<String>,
61}
62
63impl Default for ConnectionStatus {
64	fn default() -> Self {
65		Self {
66			state:ConnectionState::Disconnected,
67
68			state_since:Instant::now(),
69
70			connection_attempts:0,
71
72			last_connected:None,
73
74			last_disconnected:None,
75
76			total_uptime:Duration::ZERO,
77
78			last_error:None,
79		}
80	}
81}
82
83impl ConnectionStatus {
84	/// Create a new connection status
85	pub fn new() -> Self { Self::default() }
86
87	/// Update connection state
88	pub fn update_state(&mut self, new_state:ConnectionState, error:Option<String>) {
89		if new_state != self.state {
90			// Track downtime if disconnecting
91			if self.state == ConnectionState::Connected {
92				if let Some(connected_since) = self.last_connected {
93					self.total_uptime += connected_since.elapsed();
94				}
95			}
96
97			// Update timestamps
98			match new_state {
99				ConnectionState::Connected => {
100					self.last_connected = Some(Instant::now());
101
102					self.connection_attempts += 1;
103				},
104
105				ConnectionState::Disconnected | ConnectionState::Failed => {
106					self.last_disconnected = Some(Instant::now());
107				},
108
109				_ => {},
110			}
111
112			self.state = new_state;
113
114			self.state_since = Instant::now();
115
116			self.last_error = error;
117		}
118	}
119
120	/// Check if connection is currently active
121	pub fn is_connected(&self) -> bool { self.state == ConnectionState::Connected }
122
123	/// Check if connection is in a healthy state
124	pub fn is_healthy(&self) -> bool { matches!(self.state, ConnectionState::Connected | ConnectionState::Connecting) }
125
126	/// Get the duration the connection has been in its current state
127	pub fn current_state_duration(&self) -> Duration { self.state_since.elapsed() }
128
129	/// Get the duration since last successful connection
130	pub fn time_since_last_connection(&self) -> Option<Duration> { self.last_connected.map(|t| t.elapsed()) }
131}