#![allow(non_local_definitions)]
use std::{future::Future, time::Duration};
use abscissa_core::{Component, FrameworkError, Shutdown};
use color_eyre::Report;
use tokio::runtime::Runtime;
use crate::prelude::*;
const TOKIO_SHUTDOWN_TIMEOUT: Duration = Duration::from_secs(20);
#[derive(Component, Debug)]
pub struct TokioComponent {
pub rt: Option<Runtime>,
}
impl TokioComponent {
#[allow(clippy::unwrap_in_result)]
pub fn new() -> Result<Self, FrameworkError> {
Ok(Self {
rt: Some(
tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()
.expect("runtime building should not fail"),
),
})
}
}
async fn shutdown() {
imp::shutdown().await;
}
pub(crate) trait RuntimeRun {
fn run(self, fut: impl Future<Output = Result<(), Report>>);
}
impl RuntimeRun for Runtime {
fn run(self, fut: impl Future<Output = Result<(), Report>>) {
let result = self.block_on(async move {
tokio::select! {
biased;
_ = shutdown() => Ok(()),
result = fut => result,
}
});
info!(
?TOKIO_SHUTDOWN_TIMEOUT,
"waiting for async tokio tasks to shut down"
);
self.shutdown_timeout(TOKIO_SHUTDOWN_TIMEOUT);
match result {
Ok(()) => {
info!("shutting down Zebra");
}
Err(error) => {
warn!(?error, "shutting down Zebra due to an error");
APPLICATION.shutdown(Shutdown::Forced);
}
}
}
}
#[cfg(unix)]
mod imp {
use tokio::signal::unix::{signal, SignalKind};
pub(super) async fn shutdown() {
tokio::select! {
_ = sig(SignalKind::interrupt(), "SIGINT") => {}
_ = sig(SignalKind::terminate(), "SIGTERM") => {}
};
}
#[instrument]
async fn sig(kind: SignalKind, name: &'static str) {
signal(kind)
.expect("Failed to register signal handler")
.recv()
.await;
zebra_chain::shutdown::set_shutting_down();
#[cfg(feature = "progress-bar")]
howudoin::disable();
info!(
target: "zebrad::signal",
"received {}, starting shutdown",
name,
);
}
}
#[cfg(not(unix))]
mod imp {
pub(super) async fn shutdown() {
tokio::signal::ctrl_c()
.await
.expect("listening for ctrl-c signal should never fail");
zebra_chain::shutdown::set_shutting_down();
#[cfg(feature = "progress-bar")]
howudoin::disable();
info!(
target: "zebrad::signal",
"received Ctrl-C, starting shutdown",
);
}
}