Skip to main content

syncweb_core/sync/
sessions.rs

1use 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}