syncweb_core/sync/
sessions.rs1use std::sync::{Mutex, OnceLock};
2
3use iroh_docs::NamespaceId;
4use tokio::sync::mpsc;
5
6use super::SyncCommand;
7
8type CancelSender = mpsc::UnboundedSender<SyncCommand>;
9type Registry = Vec<(NamespaceId, CancelSender)>;
10
11static REGISTRY: OnceLock<Mutex<Registry>> = OnceLock::new();
12
13fn registry() -> &'static Mutex<Registry> {
14 REGISTRY.get_or_init(|| Mutex::new(Vec::new()))
15}
16
17pub struct ActiveSession {
18 namespace: NamespaceId,
19}
20
21fn lock_registry() -> std::sync::MutexGuard<'static, Registry> {
22 registry().lock().unwrap_or_else(std::sync::PoisonError::into_inner)
23}
24
25impl ActiveSession {
26 #[must_use]
27 pub fn register(namespace: NamespaceId, cancel: CancelSender) -> Self {
28 let mut guard = lock_registry();
29 guard.retain(|(id, _)| *id != namespace);
30 guard.push((namespace, cancel));
31 drop(guard);
32 Self { namespace }
33 }
34}
35
36impl Drop for ActiveSession {
37 fn drop(&mut self) {
38 if let Ok(mut guard) = registry().lock() {
39 guard.retain(|(id, _)| *id != self.namespace);
40 }
41 }
42}
43
44#[must_use]
45pub fn cancel_session(namespace: NamespaceId) -> bool {
46 let mut guard = lock_registry();
47 if let Some(pos) = guard.iter().position(|(id, _)| *id == namespace) {
48 let (_, cancel) = guard.remove(pos);
49 drop(guard);
50 return cancel.send(SyncCommand::Cancel).is_ok();
51 }
52 false
53}
54
55#[must_use]
56pub fn is_active(namespace: NamespaceId) -> bool {
57 let guard = lock_registry();
58 let active = guard.iter().any(|(id, _)| *id == namespace);
59 drop(guard);
60 active
61}