use tokio::sync::broadcast;
#[derive(Clone)]
pub struct ShutdownHandle {
tx: broadcast::Sender<()>,
}
impl ShutdownHandle {
pub fn new() -> Self {
let (tx, _) = broadcast::channel(1);
Self { tx }
}
pub fn shutdown(&self) {
let _ = self.tx.send(());
}
pub async fn wait_shutdown(&self) {
let mut rx = self.tx.subscribe();
let _ = rx.recv().await;
}
pub fn subscribe(&self) -> broadcast::Receiver<()> {
self.tx.subscribe()
}
}
impl Default for ShutdownHandle {
fn default() -> Self {
Self::new()
}
}
pub async fn wait_for_signal() {
#[cfg(unix)]
{
use tokio::signal::unix::{signal, SignalKind};
let mut sigterm = signal(SignalKind::terminate()).expect("Failed to setup SIGTERM handler");
let mut sigint = signal(SignalKind::interrupt()).expect("Failed to setup SIGINT handler");
tokio::select! {
_ = sigterm.recv() => {
tracing::info!("Received SIGTERM, shutting down gracefully");
}
_ = sigint.recv() => {
tracing::info!("Received SIGINT, shutting down gracefully");
}
}
}
#[cfg(not(unix))]
{
tokio::signal::ctrl_c().await.expect("Failed to listen for Ctrl+C");
tracing::info!("Received Ctrl+C, shutting down gracefully");
}
}