use async_process::Child;
use std::sync::Arc;
use tokio::sync::Mutex;
#[derive(Clone)]
pub struct Daemons(Arc<Mutex<Option<Vec<Daemon>>>>);
pub struct Daemon(Child);
impl Default for Daemons {
fn default() -> Self {
Self(Arc::new(Mutex::new(Some(Vec::new()))))
}
}
impl Daemons {
pub async fn add_daemon(&self, child: Child) {
let mut guard = self.0.lock().await;
if let Some(v) = guard.as_mut() {
v.push(Daemon(child));
} else {
*guard = Some(vec![Daemon(child)])
}
}
pub async fn shutdown(&mut self) {
let daemons = {
let mut guard = self.0.lock().await;
guard.take().unwrap_or_default()
};
for mut daemon in daemons.into_iter() {
daemon.shutdown().await;
}
}
}
impl Daemon {
async fn shutdown(&mut self) {
tokio::select! {
_ = tokio::time::sleep(tokio::time::Duration::from_secs(10)) => {
let _ = self.0.kill();
}
_ = self.0.status() => {},
}
}
}