diff --git a/Cargo.lock b/Cargo.lock index c7fcdad..e7754b9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -931,6 +931,15 @@ dependencies = [ "digest", ] +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + [[package]] name = "smallvec" version = "1.13.2" @@ -1018,6 +1027,7 @@ dependencies = [ "mio", "num_cpus", "pin-project-lite", + "signal-hook-registry", "socket2", "tokio-macros", "windows-sys 0.48.0", diff --git a/Cargo.toml b/Cargo.toml index 59d5927..77cd694 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,6 @@ axum = "0.7" dotenv = "0.15" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.96" -tokio = { version = "1", features = ["macros", "rt-multi-thread"] } +tokio = { version = "1", features = ["macros", "rt-multi-thread", "signal"] } chrono = "0.4.31" wallet-pass = "0.4.0" diff --git a/src/main.rs b/src/main.rs index 5cf352b..d0ed384 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,10 +1,12 @@ +//! Web service to create Apple Wallet passes. + use axum::{routing::get, Router}; use tokio::net::TcpListener; +use tokio::signal; mod models; mod passes; -extern crate dotenv; use dotenv::dotenv; use passes::passes_handler; @@ -24,6 +26,35 @@ async fn main() { .unwrap(); axum::serve(listener, app.into_make_service()) + .with_graceful_shutdown(shutdown_signal()) .await .unwrap(); } + +/// Graceful shutdown, useful for Docker containers. +/// +/// Copied from the +/// [axum graceful-shutdown example](https://github.com/tokio-rs/axum/blob/87b86a7066c320cb388ad4d27f32e7092b56b52f/examples/graceful-shutdown/src/main.rs). +async fn shutdown_signal() { + let ctrl_c = async { + signal::ctrl_c() + .await + .expect("failed to install Ctrl+C handler"); + }; + + #[cfg(unix)] + let terminate = async { + signal::unix::signal(signal::unix::SignalKind::terminate()) + .expect("failed to install signal handler") + .recv() + .await; + }; + + #[cfg(not(unix))] + let terminate = std::future::pending::<()>(); + + tokio::select! { + _ = ctrl_c => {}, + _ = terminate => {}, + } +}