use std::time::Duration;
use tokio_util::sync::CancellationToken;
use crate::logging::Phase;
pub const GRACE: Duration = Duration::from_secs(30);
pub async fn graceful<F>(shutdown: CancellationToken, join_future: F) -> F::Output
where
F: std::future::Future + Send,
{
let mut pinned: std::pin::Pin<Box<F>> = Box::pin(join_future);
tokio::select! {
biased;
output = &mut pinned => {
return output;
}
_ = shutdown.cancelled() => {
tracing::info!(
phase = %Phase::Daemon,
grace_ms = GRACE.as_millis() as u64,
"shutdown token tripped; entering graceful shutdown",
);
}
}
let result = tokio::time::timeout(GRACE, pinned.as_mut()).await;
match result {
Ok(val) => val,
Err(_timeout) => {
tracing::warn!(
phase = %Phase::Daemon,
grace_ms = GRACE.as_millis() as u64,
"graceful shutdown deadline expired; waiting for runtime to finish",
);
pinned.await
},
}
}