use std::collections::HashMap;
use std::path::PathBuf;
use std::sync::Arc;
use std::sync::LazyLock;
use std::sync::atomic::AtomicU32;
use std::sync::atomic::Ordering;
use tokio::sync::Mutex;
use tokio::task::JoinHandle;
use tracing::info;
use crate::brp_tools::Port;
use crate::error::Error;
use crate::error::Result;
pub(super) static WATCH_MANAGER: LazyLock<Arc<Mutex<WatchManager>>> =
std::sync::LazyLock::new(|| Arc::new(Mutex::new(WatchManager::new())));
#[derive(Debug, Clone)]
pub(super) struct WatchInfo {
pub(super) id: u32,
pub(super) entity_id: u64,
pub(super) kind: String,
pub(super) log_path: PathBuf,
pub(super) port: Port,
}
pub(super) struct WatchManager {
next_watch_id: AtomicU32,
pub(super) active_watches: HashMap<u32, (WatchInfo, JoinHandle<()>)>,
}
impl WatchManager {
fn new() -> Self {
Self {
next_watch_id: AtomicU32::new(1),
active_watches: HashMap::new(),
}
}
pub(super) fn next_id(&self) -> u32 { self.next_watch_id.fetch_add(1, Ordering::SeqCst) }
pub(super) fn stop_watch(&mut self, watch_id: u32) -> Result<()> {
if let Some((info, handle)) = self.active_watches.remove(&watch_id) {
info!("Stopping watch {watch_id} for entity {}", info.entity_id);
handle.abort();
Ok(())
} else {
Err(error_stack::Report::new(Error::WatchOperation(format!(
"Failed to stop watch {watch_id}: watch not found"
))))
}
}
pub(super) fn list_active_watches(&self) -> Vec<WatchInfo> {
self.active_watches
.values()
.map(|(info, _)| info.clone())
.collect()
}
}