use std::collections::HashMap; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, Mutex}; use tokio::process::Child; use tokio::sync::Mutex as AsyncMutex; #[derive(Clone)] struct ActiveProcess { child: Arc>, cancellation_requested: Arc, } impl ActiveProcess { fn new(child: Arc>, cancellation_requested: Arc) -> Self { Self { child, cancellation_requested, } } } #[derive(Clone, Default)] pub struct ProcessRegistry { ticket_processes: Arc>>, task_processes: Arc>>, } impl ProcessRegistry { pub fn register_ticket( &self, ticket_id: &str, child: Arc>, cancellation_requested: Arc, ) { let mut processes = self .ticket_processes .lock() .unwrap_or_else(|poison| poison.into_inner()); processes.insert( ticket_id.to_string(), ActiveProcess::new(child, cancellation_requested), ); } pub fn unregister_ticket(&self, ticket_id: &str) { let mut processes = self .ticket_processes .lock() .unwrap_or_else(|poison| poison.into_inner()); processes.remove(ticket_id); } pub async fn cancel_ticket(&self, ticket_id: &str) -> bool { self.cancel_process(&self.ticket_processes, ticket_id).await } pub fn register_task( &self, task_id: &str, child: Arc>, cancellation_requested: Arc, ) { let mut processes = self .task_processes .lock() .unwrap_or_else(|poison| poison.into_inner()); processes.insert( task_id.to_string(), ActiveProcess::new(child, cancellation_requested), ); } pub fn unregister_task(&self, task_id: &str) { let mut processes = self .task_processes .lock() .unwrap_or_else(|poison| poison.into_inner()); processes.remove(task_id); } pub async fn cancel_task(&self, task_id: &str) -> bool { self.cancel_process(&self.task_processes, task_id).await } async fn cancel_process( &self, map: &Arc>>, entity_id: &str, ) -> bool { let process = { let processes = map.lock().unwrap_or_else(|poison| poison.into_inner()); processes.get(entity_id).cloned() }; let Some(process) = process else { return false; }; process.cancellation_requested.store(true, Ordering::SeqCst); let mut child = process.child.lock().await; let _ = child.start_kill(); true } }