use std::sync::{Mutex, OnceLock};
use iroh_docs::NamespaceId;
use tokio::sync::mpsc;
use super::SyncCommand;
type CancelSender = mpsc::UnboundedSender<SyncCommand>;
type Registry = Vec<(NamespaceId, CancelSender)>;
static REGISTRY: OnceLock<Mutex<Registry>> = OnceLock::new();
fn registry() -> &'static Mutex<Registry> {
REGISTRY.get_or_init(|| Mutex::new(Vec::new()))
}
pub struct ActiveSession {
namespace: NamespaceId,
}
fn lock_registry() -> std::sync::MutexGuard<'static, Registry> {
registry().lock().unwrap_or_else(std::sync::PoisonError::into_inner)
}
impl ActiveSession {
#[must_use]
pub fn register(namespace: NamespaceId, cancel: CancelSender) -> Self {
let mut guard = lock_registry();
guard.retain(|(id, _)| *id != namespace);
guard.push((namespace, cancel));
drop(guard);
Self { namespace }
}
}
impl Drop for ActiveSession {
fn drop(&mut self) {
if let Ok(mut guard) = registry().lock() {
guard.retain(|(id, _)| *id != self.namespace);
}
}
}
#[must_use]
pub fn cancel_session(namespace: NamespaceId) -> bool {
let mut guard = lock_registry();
if let Some(pos) = guard.iter().position(|(id, _)| *id == namespace) {
let (_, cancel) = guard.remove(pos);
drop(guard);
return cancel.send(SyncCommand::Cancel).is_ok();
}
false
}
#[must_use]
pub fn is_active(namespace: NamespaceId) -> bool {
let guard = lock_registry();
let active = guard.iter().any(|(id, _)| *id == namespace);
drop(guard);
active
}