use crate::prelude::*; pub struct Terminator { signal: Promise<()>, completion: JoinHandle>, } impl Terminator { pub async fn terminate(self) -> Result<()> { match self.signal.send(()) { Ok(()) => {} Err(_) => log::warn!("Termination channel is dropped"), } self.completion.await??; Ok(()) } /// Used to spawn managed tasks with support for graceful shutdown pub fn spawn(launcher: Fun) -> Terminator where Fun: FnOnce(Deferred<()>) -> Fut, Fut: Future> + Send + 'static, { let (signal, rx) = oneshot(); let future = launcher(rx); let completion = tokio::task::spawn(future); Terminator { signal, completion } } }