appcore_gateway/
connection.rs1use appcore_contracts::InstallationId;
14use appcore_types::{ClusterId, CoreId, TenantId};
15use axum::extract::ws::Message;
16use std::sync::atomic::{AtomicU64, Ordering};
17use std::sync::Arc;
18use tokio::sync::mpsc::Sender;
19
20pub const CONNECTION_BUFFER_CAPACITY: usize = 128;
22
23static CONNECTION_GENERATION: AtomicU64 = AtomicU64::new(1);
25
26#[derive(Debug, Clone, PartialEq, Eq, Hash)]
28pub struct WorkerConnectionKey {
29 pub tenant_id: TenantId,
31 pub installation_id: InstallationId,
33 pub core_id: CoreId,
35}
36
37#[derive(Debug, Clone)]
39pub struct WorkerConnection {
40 pub key: WorkerConnectionKey,
42 pub sender: Sender<Message>,
44 cluster_id: Option<ClusterId>,
45 generation: u64,
46 last_heartbeat_ms: Arc<AtomicU64>,
48}
49
50impl WorkerConnection {
51 pub fn new(key: WorkerConnectionKey, sender: Sender<Message>, now_ms: u64) -> Self {
53 Self::new_inner(key, None, sender, now_ms)
54 }
55
56 pub fn new_in_cluster(
58 key: WorkerConnectionKey,
59 cluster_id: ClusterId,
60 sender: Sender<Message>,
61 now_ms: u64,
62 ) -> Self {
63 Self::new_inner(key, Some(cluster_id), sender, now_ms)
64 }
65
66 fn new_inner(
67 key: WorkerConnectionKey,
68 cluster_id: Option<ClusterId>,
69 sender: Sender<Message>,
70 now_ms: u64,
71 ) -> Self {
72 Self {
73 key,
74 sender,
75 cluster_id,
76 generation: CONNECTION_GENERATION.fetch_add(1, Ordering::Relaxed),
77 last_heartbeat_ms: Arc::new(AtomicU64::new(now_ms)),
78 }
79 }
80
81 pub fn cluster_id(&self) -> Option<&ClusterId> {
83 self.cluster_id.as_ref()
84 }
85
86 pub(crate) fn generation(&self) -> u64 {
87 self.generation
88 }
89
90 pub fn update_heartbeat(&self, now_ms: u64) {
92 self.last_heartbeat_ms.store(now_ms, Ordering::SeqCst);
93 }
94
95 pub fn last_heartbeat(&self) -> u64 {
97 self.last_heartbeat_ms.load(Ordering::SeqCst)
98 }
99
100 pub fn send(&self, message: Message) -> Result<(), crate::error::GatewayError> {
102 self.sender.try_send(message).map_err(|_| {
103 crate::error::GatewayError::Transport("worker connection closed".to_string())
104 })
105 }
106}
107
108#[derive(Debug, Clone)]
110pub struct ClientConnection {
111 pub connection_id: String,
113 pub tenant_id: TenantId,
115 pub session_id: String,
117 pub sender: Sender<Message>,
119}
120
121impl ClientConnection {
122 pub fn new(
124 connection_id: String,
125 tenant_id: TenantId,
126 session_id: String,
127 sender: Sender<Message>,
128 ) -> Self {
129 Self {
130 connection_id,
131 tenant_id,
132 session_id,
133 sender,
134 }
135 }
136
137 pub fn send(&self, message: Message) -> Result<(), crate::error::GatewayError> {
139 self.sender.try_send(message).map_err(|_| {
140 crate::error::GatewayError::Transport("client connection closed".to_string())
141 })
142 }
143}