Files
zesdex/apps/infrastructure/src/bgbash/control.rs
T

79 lines
2.0 KiB
Rust
Raw Normal View History

//! Background bash control — list, cancel, and inspect background processes.
use std::collections::HashMap;
use std::sync::{Arc, Mutex, OnceLock};
use tracing::error;
use super::job::BashJob;
/// Global accessor for the shared BashControl singleton.
///
/// Used by the Bash tool (to register jobs) and BashKill (to look them up).
pub fn bash_control() -> &'static BashControl {
static BASH_CONTROL: OnceLock<BashControl> = OnceLock::new();
BASH_CONTROL.get_or_init(BashControl::new)
}
/// Central registry of all running background bash jobs.
pub struct BashControl {
jobs: Mutex<HashMap<String, Arc<BashJob>>>,
}
impl BashControl {
pub fn new() -> Self {
BashControl {
jobs: Mutex::new(HashMap::new()),
}
}
}
impl Default for BashControl {
fn default() -> Self {
Self::new()
}
}
impl BashControl {
/// Register a new background job.
pub fn register(&self, job: Arc<BashJob>) {
if let Ok(mut guard) = self.jobs.lock() {
guard.insert(job.id.clone(), job);
}
}
/// Cancel a job by ID.
pub fn cancel(&self, id: &str) -> bool {
if let Ok(mut guard) = self.jobs.lock() {
if let Some(job) = guard.remove(id) {
job.cancel();
return true;
}
}
false
}
/// List all active jobs.
pub fn list(&self) -> Vec<(String, String, bool)> {
let mut guard = match self.jobs.lock() {
Ok(g) => g,
Err(poisoned) => {
error!("bgbash jobs mutex poisoned, recovering");
poisoned.into_inner()
}
};
guard.retain(|_, j| j.is_running());
guard
.iter()
.map(|(id, job)| (id.clone(), job.command.clone(), job.is_running()))
.collect()
}
/// Clean up completed jobs.
pub fn prune(&self) {
if let Ok(mut guard) = self.jobs.lock() {
guard.retain(|_, j| j.is_running());
}
}
}