Mountain/IPC/Common/
ConnectionStatus.rs1use std::time::{Duration, Instant};
7
8use serde::{Deserialize, Serialize};
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
12pub enum ConnectionState {
13 Connected,
15
16 Connecting,
18
19 Disconnected,
21
22 Failed,
24
25 Closing,
27
28 Closed,
30}
31
32#[derive(Debug, Clone, Serialize)]
34pub struct ConnectionStatus {
35 pub state:ConnectionState,
37
38 #[serde(skip)]
41 pub state_since:Instant,
42
43 pub connection_attempts:u32,
45
46 #[serde(skip)]
49 pub last_connected:Option<Instant>,
50
51 #[serde(skip)]
54 pub last_disconnected:Option<Instant>,
55
56 pub total_uptime:Duration,
58
59 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 pub fn new() -> Self { Self::default() }
86
87 pub fn update_state(&mut self, new_state:ConnectionState, error:Option<String>) {
89 if new_state != self.state {
90 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 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 pub fn is_connected(&self) -> bool { self.state == ConnectionState::Connected }
122
123 pub fn is_healthy(&self) -> bool { matches!(self.state, ConnectionState::Connected | ConnectionState::Connecting) }
125
126 pub fn current_state_duration(&self) -> Duration { self.state_since.elapsed() }
128
129 pub fn time_since_last_connection(&self) -> Option<Duration> { self.last_connected.map(|t| t.elapsed()) }
131}