supabase_realtime_rs/client/
state.rs1use super::connection::ConnectionState;
2use crate::channel::RealtimeChannel;
3use crate::infrastructure::TaskManager;
4use std::sync::Arc;
5use tokio::sync::watch;
6
7pub struct ClientState {
10 pub ref_counter: u64,
12
13 pub pending_heartbeat_ref: Option<String>,
15
16 pub channels: Vec<Arc<RealtimeChannel>>,
18
19 pub task_manager: TaskManager,
21
22 pub was_manual_disconnect: bool,
24
25 pub state_change_tx: Option<watch::Sender<(ConnectionState, bool)>>,
27}
28
29impl ClientState {
30 pub fn new() -> Self {
31 Self {
32 ref_counter: 0,
33 pending_heartbeat_ref: None,
34 channels: Vec::new(),
35 task_manager: TaskManager::new(),
36 was_manual_disconnect: false,
37 state_change_tx: None,
38 }
39 }
40
41 pub fn make_ref(&mut self) -> String {
43 self.ref_counter += 1;
44 self.ref_counter.to_string()
45 }
46
47 pub fn notify_state_change(&self, state: ConnectionState, manual: bool) {
49 if let Some(tx) = &self.state_change_tx
50 && tx.send((state, manual)).is_err()
51 {
52 tracing::debug!(
53 "State change watcher disconnected, could not notify state: {:?}",
54 state
55 );
56 }
57 }
58}
59
60impl Default for ClientState {
61 fn default() -> Self {
62 Self::new()
63 }
64}
65
66#[cfg(test)]
67mod tests {
68 use super::*; #[test]
71 fn test_make_ref_increments() {
72 let mut state = ClientState::default();
73 assert_eq!(state.ref_counter, 0);
74
75 let ref1 = state.make_ref();
76 assert_eq!(state.ref_counter, 1);
77 assert_eq!(ref1, "1");
78
79 let ref2 = state.make_ref();
80 assert_eq!(state.ref_counter, 2);
81 assert_eq!(ref2, "2");
82
83 assert_ne!(ref1, ref2);
84 }
85
86 #[test]
87 fn test_make_ref_start_at_zero() {
88 let state = ClientState::default();
89 assert_eq!(state.ref_counter, 0);
90 }
91}