Skip to main content

gateway_runtime/
shutdown.rs

1//! # Shutdown
2//!
3//! ## Purpose
4//! Provides utilities for graceful shutdown of the gateway server.
5//!
6//! ## Scope
7//! This module defines:
8//! -   `GracefulShutdown`: A struct to manage shutdown signals and coordination.
9//! -   `wait_for_signal`: A helper to wait for SIGINT/SIGTERM.
10
11use core::future::Future;
12use core::pin::Pin;
13use core::task::{Context, Poll};
14
15#[cfg(feature = "std")]
16use tokio::signal;
17
18/// A future that resolves when a shutdown signal is received.
19pub struct ShutdownSignal {
20    #[cfg(feature = "std")]
21    inner: Pin<Box<dyn Future<Output = ()> + Send + Sync>>,
22}
23
24impl ShutdownSignal {
25    /// Creates a new shutdown signal listener.
26    pub fn new() -> Self {
27        #[cfg(feature = "std")]
28        {
29            let fut = async {
30                let ctrl_c = async {
31                    signal::ctrl_c()
32                        .await
33                        .expect("failed to install Ctrl+C handler");
34                };
35
36                #[cfg(unix)]
37                let terminate = async {
38                    signal::unix::signal(signal::unix::SignalKind::terminate())
39                        .expect("failed to install signal handler")
40                        .recv()
41                        .await;
42                };
43
44                #[cfg(not(unix))]
45                let terminate = std::future::pending::<()>();
46
47                tokio::select! {
48                    _ = ctrl_c => {},
49                    _ = terminate => {},
50                }
51            };
52            Self {
53                inner: Box::pin(fut),
54            }
55        }
56        #[cfg(not(feature = "std"))]
57        {
58            Self {}
59        }
60    }
61}
62
63impl Future for ShutdownSignal {
64    type Output = ();
65
66    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
67        #[cfg(feature = "std")]
68        return self.inner.as_mut().poll(cx);
69        #[cfg(not(feature = "std"))]
70        Poll::Pending
71    }
72}
73
74/// Helper function to wait for a shutdown signal.
75pub async fn wait_for_signal() {
76    ShutdownSignal::new().await
77}