pub struct ShutdownHandler { /* private fields */ }
Expand description
A graceful shutdown handler that allows all parts of an application to trigger a shutdown.
§Example
use std::pin::pin;
use std::sync::Arc;
use shutdown_handler::{ShutdownHandler, SignalOrComplete};
// Create the shutdown handler
let shutdown = Arc::new(ShutdownHandler::new());
// Shutdown on SIGTERM
shutdown.spawn_sigterm_handler().unwrap();
// Spawn a few service workers
let mut workers = tokio::task::JoinSet::new();
for port in 0..4 {
workers.spawn(service(Arc::clone(&shutdown), port));
}
// await all workers and collect the errors
let mut errors = vec![];
while let Some(result) = workers.join_next().await {
// unwrap any JoinErrors that happen if the tokio task panicked
let result = result.unwrap();
// did our service error?
if let Err(e) = result {
errors.push(e);
}
}
assert_eq!(errors, ["port closed"]);
// Define our services to loop on work and shutdown gracefully
async fn service(shutdown: Arc<ShutdownHandler>, port: u16) -> Result<(), &'static str> {
// a work loop that handles events
for request in 0.. {
let handle = pin!(handle_request(port, request));
match shutdown.wait_for_signal_or_future(handle).await {
// We finished handling the request without any interuptions. Continue
SignalOrComplete::Completed(Ok(_)) => {}
// There was an error handling the request, let's shutdown
SignalOrComplete::Completed(Err(e)) => {
shutdown.shutdown();
return Err(e);
}
// There was a shutdown signal raised while handling this request
SignalOrComplete::ShutdownSignal(handle) => {
// We will finish handling the request but then exit
return handle.await;
}
}
}
Ok(())
}
async fn handle_request(port: u16, request: usize) -> Result<(), &'static str> {
// simulate some work being done
tokio::time::sleep(std::time::Duration::from_millis(10)).await;
// simulate an error
if port == 3 && request > 12 {
Err("port closed")
} else {
Ok(())
}
}
Implementations§
Source§impl ShutdownHandler
impl ShutdownHandler
pub fn new() -> Self
Sourcepub fn sigterm() -> Result<Arc<Self>>
pub fn sigterm() -> Result<Arc<Self>>
Creates a new ShutdownHandler
and registers the sigterm handler
Sourcepub fn spawn_sigterm_handler(self: &Arc<Self>) -> Result<()>
pub fn spawn_sigterm_handler(self: &Arc<Self>) -> Result<()>
Registers the signal event SIGTERM
to trigger an application shutdown
Sourcepub fn spawn_signal_handler(
self: &Arc<Self>,
signal_kind: SignalKind,
) -> Result<()>
pub fn spawn_signal_handler( self: &Arc<Self>, signal_kind: SignalKind, ) -> Result<()>
Registers a signal event to trigger an application shutdown
Sourcepub fn wait_for_signal(&self) -> ShutdownSignal<'_> ⓘ
pub fn wait_for_signal(&self) -> ShutdownSignal<'_> ⓘ
Returns a future that waits for the shutdown signal.
You can use this like an async function.
Sourcepub async fn wait_for_signal_or_future<F: Future + Unpin>(
&self,
f: F,
) -> SignalOrComplete<F>
pub async fn wait_for_signal_or_future<F: Future + Unpin>( &self, f: F, ) -> SignalOrComplete<F>
This method will try to complete the given future, but will give up if the shutdown signal is raised. The unfinished future is returned in case it is not cancel safe and you need to complete it
use std::sync::Arc;
use std::pin::pin;
use shutdown_handler::{ShutdownHandler, SignalOrComplete};
async fn important_work() -> i32 {
tokio::time::sleep(std::time::Duration::from_secs(2)).await;
42
}
let shutdown = Arc::new(ShutdownHandler::new());
// another part of the application signals a shutdown
let shutdown2 = Arc::clone(&shutdown);
let handle = tokio::spawn(async move {
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
shutdown2.shutdown();
});
let work = pin!(important_work());
match shutdown.wait_for_signal_or_future(work).await {
SignalOrComplete::Completed(res) => println!("important work completed without interuption: {res}"),
SignalOrComplete::ShutdownSignal(work) => {
println!("shutdown signal recieved");
let res = work.await;
println!("important work completed: {res}");
},
}
Trait Implementations§
Source§impl Debug for ShutdownHandler
impl Debug for ShutdownHandler
Source§impl Default for ShutdownHandler
impl Default for ShutdownHandler
Source§fn default() -> ShutdownHandler
fn default() -> ShutdownHandler
Returns the “default value” for a type. Read more
Auto Trait Implementations§
impl !Freeze for ShutdownHandler
impl RefUnwindSafe for ShutdownHandler
impl Send for ShutdownHandler
impl Sync for ShutdownHandler
impl Unpin for ShutdownHandler
impl UnwindSafe for ShutdownHandler
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more