apollo_router/router/event/
shutdown.rs

1use std::pin::Pin;
2
3use derivative::Derivative;
4use derive_more::Display;
5use futures::prelude::*;
6
7use crate::router::Event;
8use crate::router::Event::Shutdown;
9
10type ShutdownFuture = Pin<Box<dyn Future<Output = ()> + Send>>;
11
12/// Specifies when the Router’s HTTP server should gracefully shutdown
13#[derive(Display, Derivative)]
14#[derivative(Debug)]
15#[non_exhaustive]
16pub enum ShutdownSource {
17    /// No graceful shutdown
18    #[display("None")]
19    None,
20
21    /// A custom shutdown future.
22    #[display("Custom")]
23    Custom(#[derivative(Debug = "ignore")] ShutdownFuture),
24
25    /// Watch for Ctl-C signal.
26    #[display("CtrlC")]
27    CtrlC,
28}
29
30impl ShutdownSource {
31    /// Convert this shutdown hook into a future. Allows for unified handling later.
32    pub(crate) fn into_stream(self) -> impl Stream<Item = Event> {
33        match self {
34            ShutdownSource::None => stream::pending::<Event>().boxed(),
35            ShutdownSource::Custom(future) => future.map(|_| Shutdown).into_stream().boxed(),
36            ShutdownSource::CtrlC => {
37                #[cfg(not(unix))]
38                {
39                    async {
40                        tokio::signal::ctrl_c()
41                            .await
42                            .expect("Failed to install CTRL+C signal handler");
43                    }
44                    .map(|_| Shutdown)
45                    .into_stream()
46                    .boxed()
47                }
48
49                #[cfg(unix)]
50                future::select(
51                    tokio::signal::ctrl_c().map(|s| s.ok()).boxed(),
52                    async {
53                        tokio::signal::unix::signal(tokio::signal::unix::SignalKind::terminate())
54                            .expect("Failed to install SIGTERM signal handler")
55                            .recv()
56                            .await
57                    }
58                    .boxed(),
59                )
60                .map(|_| Shutdown)
61                .into_stream()
62                .boxed()
63            }
64        }
65    }
66}