apollo_router/router/event/
shutdown.rs1use 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#[derive(Display, Derivative)]
14#[derivative(Debug)]
15#[non_exhaustive]
16pub enum ShutdownSource {
17 #[display("None")]
19 None,
20
21 #[display("Custom")]
23 Custom(#[derivative(Debug = "ignore")] ShutdownFuture),
24
25 #[display("CtrlC")]
27 CtrlC,
28}
29
30impl ShutdownSource {
31 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}