autoconnect_common/
registry.rs1use std::collections::HashMap;
2
3use futures::channel::mpsc;
4use futures_locks::RwLock;
5use uuid::Uuid;
6
7use autopush_common::errors::{ApcErrorKind, Result};
8use autopush_common::notification::Notification;
9
10use crate::protocol::ServerNotification;
11
12#[derive(Debug)]
14struct RegisteredClient {
15 pub uaid: Uuid,
17 pub uid: Uuid,
19 pub tx: mpsc::UnboundedSender<ServerNotification>,
21}
22
23#[derive(Default)]
25pub struct ClientRegistry {
26 clients: RwLock<HashMap<Uuid, RegisteredClient>>,
27}
28
29impl ClientRegistry {
30 pub async fn connect(
35 &self,
36 uaid: Uuid,
37 uid: Uuid,
38 ) -> mpsc::UnboundedReceiver<ServerNotification> {
39 trace!("ClientRegistry::connect");
40 let (tx, snotif_stream) = mpsc::unbounded();
41 let client = RegisteredClient { uaid, uid, tx };
42 let mut clients = self.clients.write().await;
43 if let Some(client) = clients.insert(client.uaid, client) {
44 let result = client.tx.unbounded_send(ServerNotification::Disconnect);
46 if result.is_ok() {
47 debug!("ClientRegistry::connect Ghosting client, new one wants to connect");
48 }
49 }
50 snotif_stream
51 }
52
53 pub async fn notify(&self, uaid: Uuid, notif: Notification) -> Result<()> {
55 trace!("ClientRegistry::notify");
56 let clients = self.clients.read().await;
57 if let Some(client) = clients.get(&uaid) {
58 debug!("ClientRegistry::notify Found a client to deliver a notification to");
59 let result = client
60 .tx
61 .unbounded_send(ServerNotification::Notification(notif));
62 if result.is_ok() {
63 debug!("ClientRegistry::notify Dropped notification in queue");
64 return Ok(());
65 }
66 }
67 Err(ApcErrorKind::GeneralError("User not connected".into()).into())
68 }
69
70 pub async fn check_storage(&self, uaid: Uuid) -> Result<()> {
72 trace!("ClientRegistry::check_storage");
73 let clients = self.clients.read().await;
74 if let Some(client) = clients.get(&uaid) {
75 let result = client.tx.unbounded_send(ServerNotification::CheckStorage);
76 if result.is_ok() {
77 debug!("ClientRegistry::check_storage Told client to check storage");
78 return Ok(());
79 }
80 }
81 Err(ApcErrorKind::GeneralError("User not connected".into()).into())
82 }
83
84 pub async fn disconnect(&self, uaid: &Uuid, uid: &Uuid) -> Result<()> {
86 trace!("ClientRegistry::disconnect");
87 let mut clients = self.clients.write().await;
88 let client_exists = clients.get(uaid).is_some_and(|client| client.uid == *uid);
89 if client_exists {
90 clients.remove(uaid).expect("Couldn't remove client?");
91 return Ok(());
92 }
93 Err(ApcErrorKind::GeneralError("User not connected".into()).into())
94 }
95
96 pub async fn count(&self) -> usize {
97 self.clients.read().await.len()
98 }
99}