use std::fmt;
use crate::error::Result;
#[cfg(unix)]
use tokio::signal::unix::{Signal, SignalKind, signal};
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
#[expect(clippy::module_name_repetitions)]
pub enum ShutdownSignal {
Interrupt,
Terminate,
Reload,
}
pub struct Handler {
#[cfg(unix)]
sigterm: Signal,
#[cfg(unix)]
sighup: Signal,
}
impl Handler {
pub fn new() -> Result<Self> {
#[cfg(unix)]
{
Ok(Self {
sigterm: signal(SignalKind::terminate())?,
sighup: signal(SignalKind::hangup())?,
})
}
#[cfg(not(unix))]
Ok(Self {})
}
pub async fn recv(&mut self) -> ShutdownSignal {
#[cfg(unix)]
{
tokio::select! {
_ = tokio::signal::ctrl_c() => ShutdownSignal::Interrupt,
_ = self.sigterm.recv() => ShutdownSignal::Terminate,
_ = self.sighup.recv() => ShutdownSignal::Reload,
}
}
#[cfg(not(unix))]
{
tokio::signal::ctrl_c().await;
ShutdownSignal::Interrupt
}
}
}
impl fmt::Display for ShutdownSignal {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ShutdownSignal::Interrupt => write!(f, "Ctrl+C"),
ShutdownSignal::Terminate => write!(f, "SIGTERM"),
ShutdownSignal::Reload => write!(f, "SIGHUP"),
}
}
}