use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::{Mutex, broadcast};
use crate::acp::client::AcpClient;
#[derive(Clone, Debug)]
pub struct AcpProcessEvent {
pub session_id: String,
pub alive: bool,
}
#[derive(Clone)]
pub struct AcpSupervisor {
clients: Arc<Mutex<HashMap<String, Arc<AcpClient>>>>,
events: broadcast::Sender<AcpProcessEvent>,
}
impl Default for AcpSupervisor {
fn default() -> Self {
let (events, _) = broadcast::channel(64);
Self { clients: Arc::new(Mutex::new(HashMap::new())), events }
}
}
impl AcpSupervisor {
pub async fn insert(&self, session_id: String, client: Arc<AcpClient>) {
self.clients.lock().await.insert(session_id.clone(), client);
let _ = self.events.send(AcpProcessEvent { session_id, alive: true });
}
pub async fn get(&self, session_id: &str) -> Option<Arc<AcpClient>> {
self.clients.lock().await.get(session_id).cloned()
}
pub async fn snapshot(&self) -> Vec<(String, Arc<AcpClient>)> {
self.clients.lock().await.iter().map(|(k, v)| (k.clone(), v.clone())).collect()
}
pub async fn dispose(&self, session_id: &str) -> Option<Arc<AcpClient>> {
let removed = self.clients.lock().await.remove(session_id);
if removed.is_some() {
let _ = self
.events
.send(AcpProcessEvent { session_id: session_id.to_string(), alive: false });
}
removed
}
pub fn process_event_subscribe(&self) -> broadcast::Receiver<AcpProcessEvent> {
self.events.subscribe()
}
pub async fn shutdown_all(&self) {
let clients: Vec<_> = self.clients.lock().await.drain().collect();
for (_, client) in clients {
client.shutdown().await;
}
}
}