2019-08-25 02:19:11 +00:00
|
|
|
use crate::request::{FromRequest, Outcome, Request};
|
2019-12-11 00:34:23 +00:00
|
|
|
use tokio::sync::mpsc;
|
2019-08-25 02:19:11 +00:00
|
|
|
|
2020-07-22 23:10:02 +00:00
|
|
|
/// A request guard to gracefully shutdown a Rocket server.
|
|
|
|
///
|
|
|
|
/// A server shutdown is manually requested by calling [`Shutdown::shutdown()`]
|
|
|
|
/// or, if enabled, by pressing `Ctrl-C`. Rocket will finish handling any
|
|
|
|
/// pending requests and return `Ok()` to the caller of [`Rocket::launch()`].
|
2020-02-03 08:53:59 +00:00
|
|
|
///
|
|
|
|
/// [`Rocket::launch()`]: crate::Rocket::launch()
|
2019-12-20 02:11:32 +00:00
|
|
|
///
|
2019-08-25 02:19:11 +00:00
|
|
|
/// # Example
|
|
|
|
///
|
2020-06-16 12:01:26 +00:00
|
|
|
/// ```rust,no_run
|
2019-08-25 02:19:11 +00:00
|
|
|
/// # #[macro_use] extern crate rocket;
|
|
|
|
/// #
|
2020-07-22 23:10:02 +00:00
|
|
|
/// use rocket::Shutdown;
|
2019-08-25 02:19:11 +00:00
|
|
|
///
|
|
|
|
/// #[get("/shutdown")]
|
2020-07-22 23:10:02 +00:00
|
|
|
/// fn shutdown(handle: Shutdown) -> &'static str {
|
2019-08-25 02:19:11 +00:00
|
|
|
/// handle.shutdown();
|
|
|
|
/// "Shutting down..."
|
|
|
|
/// }
|
|
|
|
///
|
2020-06-14 15:57:55 +00:00
|
|
|
/// #[rocket::main]
|
|
|
|
/// async fn main() {
|
2020-06-16 12:01:26 +00:00
|
|
|
/// let result = rocket::ignite()
|
2019-08-25 02:19:11 +00:00
|
|
|
/// .mount("/", routes![shutdown])
|
|
|
|
/// .launch()
|
2020-06-16 12:01:26 +00:00
|
|
|
/// .await;
|
|
|
|
///
|
2020-07-22 19:54:52 +00:00
|
|
|
/// // If the server shut down (by visiting `/shutdown`), `result` is `Ok`.
|
2020-06-16 12:01:26 +00:00
|
|
|
/// result.expect("server failed unexpectedly");
|
2019-08-25 02:19:11 +00:00
|
|
|
/// }
|
|
|
|
/// ```
|
|
|
|
#[derive(Debug, Clone)]
|
2020-07-22 23:10:02 +00:00
|
|
|
pub struct Shutdown(pub(crate) mpsc::Sender<()>);
|
2019-08-25 02:19:11 +00:00
|
|
|
|
2020-07-22 23:10:02 +00:00
|
|
|
impl Shutdown {
|
2019-12-20 02:11:32 +00:00
|
|
|
/// Notify Rocket to shut down gracefully. This function returns
|
|
|
|
/// immediately; pending requests will continue to run until completion
|
|
|
|
/// before the actual shutdown occurs.
|
2019-08-25 02:19:11 +00:00
|
|
|
#[inline]
|
2020-12-24 01:02:40 +00:00
|
|
|
pub fn shutdown(self) {
|
2019-08-25 02:19:11 +00:00
|
|
|
// Intentionally ignore any error, as the only scenarios this can happen
|
|
|
|
// is sending too many shutdown requests or we're already shut down.
|
|
|
|
let _ = self.0.try_send(());
|
2019-12-11 00:34:23 +00:00
|
|
|
info!("Server shutdown requested, waiting for all pending requests to finish.");
|
2019-08-25 02:19:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-31 09:34:15 +00:00
|
|
|
#[crate::async_trait]
|
2020-07-22 23:10:02 +00:00
|
|
|
impl<'a, 'r> FromRequest<'a, 'r> for Shutdown {
|
2019-08-25 02:19:11 +00:00
|
|
|
type Error = std::convert::Infallible;
|
|
|
|
|
|
|
|
#[inline]
|
2020-01-31 09:34:15 +00:00
|
|
|
async fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> {
|
2020-07-23 02:22:32 +00:00
|
|
|
Outcome::Success(request.state.shutdown.clone())
|
2019-08-25 02:19:11 +00:00
|
|
|
}
|
|
|
|
}
|