Skip to main content

axum_server/
handle.rs

1use crate::{notify_once::NotifyOnce, server::Address};
2use std::{
3    sync::{
4        atomic::{AtomicUsize, Ordering},
5        Arc, Mutex,
6    },
7    time::Duration,
8};
9use tokio::time::sleep;
10
11/// A handle for shutdown and connection counting that is not tied to an
12/// address type.
13///
14/// Unlike [`Handle`], one `Control` can drive servers listening on different
15/// address types, for example TCP and Unix at the same time. Build a [`Handle`]
16/// for each listener with [`Handle::with_control`], then
17/// [`graceful_shutdown`](Self::graceful_shutdown) or [`shutdown`](Self::shutdown)
18/// drains all of them and [`connection_count`](Self::connection_count) covers
19/// every listener.
20///
21/// ```rust
22/// use axum_server::{Control, Handle};
23/// use std::net::SocketAddr;
24///
25/// let control = Control::new();
26///
27/// let handle = Handle::<SocketAddr>::with_control(control.clone());
28/// ```
29#[derive(Clone, Debug, Default)]
30pub struct Control {
31    inner: Arc<ControlInner>,
32}
33
34#[derive(Debug, Default)]
35struct ControlInner {
36    conn_count: AtomicUsize,
37    shutdown: NotifyOnce,
38    graceful: NotifyOnce,
39    graceful_dur: Mutex<Option<Duration>>,
40    conn_end: NotifyOnce,
41}
42
43impl Control {
44    /// Create a new control handle.
45    pub fn new() -> Self {
46        Self::default()
47    }
48
49    /// Get the number of live connections across all servers using this
50    /// control.
51    pub fn connection_count(&self) -> usize {
52        self.inner.conn_count.load(Ordering::SeqCst)
53    }
54
55    /// Shutdown all servers using this control.
56    pub fn shutdown(&self) {
57        self.inner.shutdown.notify_waiters();
58    }
59
60    /// Gracefully shutdown all servers using this control.
61    ///
62    /// `None` means indefinite grace period.
63    pub fn graceful_shutdown(&self, duration: Option<Duration>) {
64        *self.inner.graceful_dur.lock().unwrap() = duration;
65
66        self.inner.graceful.notify_waiters();
67    }
68
69    pub(crate) async fn wait_shutdown(&self) {
70        self.inner.shutdown.notified().await;
71    }
72
73    pub(crate) async fn wait_graceful_shutdown(&self) {
74        self.inner.graceful.notified().await;
75    }
76
77    pub(crate) async fn wait_connections_end(&self) {
78        if self.inner.conn_count.load(Ordering::SeqCst) == 0 {
79            return;
80        }
81
82        let deadline = *self.inner.graceful_dur.lock().unwrap();
83
84        match deadline {
85            Some(duration) => tokio::select! {
86                biased;
87                _ = sleep(duration) => self.shutdown(),
88                _ = self.inner.conn_end.notified() => (),
89            },
90            None => self.inner.conn_end.notified().await,
91        }
92    }
93
94    pub(crate) fn watcher(&self) -> Watcher {
95        Watcher::new(self.clone())
96    }
97}
98
99/// A handle for [`Server`](crate::server::Server).
100///
101/// It controls the server it is passed to and, through
102/// [`with_control`](Self::with_control), any number of servers sharing the same
103/// [`Control`].
104#[derive(Clone, Debug)]
105pub struct Handle<A: Address> {
106    addr: Arc<AddrSlot<A>>,
107    control: Control,
108}
109
110#[derive(Debug)]
111struct AddrSlot<A: Address> {
112    addr: Mutex<Option<A>>,
113    addr_notify: NotifyOnce,
114}
115
116// Manually implemented as the derive macro will want A to be Default.
117impl<A: Address> Default for AddrSlot<A> {
118    fn default() -> Self {
119        Self {
120            addr: Default::default(),
121            addr_notify: Default::default(),
122        }
123    }
124}
125
126impl<A: Address> Default for Handle<A> {
127    fn default() -> Self {
128        Self::new()
129    }
130}
131
132impl<A: Address> Handle<A> {
133    /// Create a new handle.
134    pub fn new() -> Self {
135        Self::with_control(Control::new())
136    }
137
138    /// Create a handle that shares shutdown and connection counting with
139    /// `control`.
140    ///
141    /// Each server should get its own `Handle` so that
142    /// [`listening`](Self::listening) reports the address of that server.
143    pub fn with_control(control: Control) -> Self {
144        Self {
145            addr: Arc::new(AddrSlot::default()),
146            control,
147        }
148    }
149
150    /// Get the shared [`Control`].
151    pub fn control(&self) -> Control {
152        self.control.clone()
153    }
154
155    /// Get the number of connections.
156    pub fn connection_count(&self) -> usize {
157        self.control.connection_count()
158    }
159
160    /// Shutdown the server.
161    pub fn shutdown(&self) {
162        self.control.shutdown();
163    }
164
165    /// Gracefully shutdown the server.
166    ///
167    /// `None` means indefinite grace period.
168    pub fn graceful_shutdown(&self, duration: Option<Duration>) {
169        self.control.graceful_shutdown(duration);
170    }
171
172    /// Returns local address and port when server starts listening.
173    ///
174    /// Returns `None` if server fails to bind.
175    pub async fn listening(&self) -> Option<A> {
176        // Wait for the server to resolve its listening address. This is a
177        // one-shot latch: if binding already failed, this returns immediately
178        // with `None` instead of waiting forever for a notification that will
179        // never come.
180        self.addr.addr_notify.notified().await;
181
182        self.addr.addr.lock().unwrap().clone()
183    }
184
185    pub(crate) fn notify_listening(&self, addr: Option<A>) {
186        *self.addr.addr.lock().unwrap() = addr;
187
188        self.addr.addr_notify.notify_waiters();
189    }
190
191    pub(crate) fn watcher(&self) -> Watcher {
192        self.control.watcher()
193    }
194
195    pub(crate) async fn wait_shutdown(&self) {
196        self.control.wait_shutdown().await;
197    }
198
199    pub(crate) async fn wait_graceful_shutdown(&self) {
200        self.control.wait_graceful_shutdown().await;
201    }
202
203    pub(crate) async fn wait_connections_end(&self) {
204        self.control.wait_connections_end().await;
205    }
206}
207
208pub(crate) struct Watcher {
209    control: Control,
210}
211
212impl Watcher {
213    fn new(control: Control) -> Self {
214        control.inner.conn_count.fetch_add(1, Ordering::SeqCst);
215
216        Self { control }
217    }
218
219    pub(crate) async fn wait_graceful_shutdown(&self) {
220        self.control.wait_graceful_shutdown().await
221    }
222
223    pub(crate) async fn wait_shutdown(&self) {
224        self.control.wait_shutdown().await
225    }
226}
227
228impl Drop for Watcher {
229    fn drop(&mut self) {
230        let count = self.control.inner.conn_count.fetch_sub(1, Ordering::SeqCst) - 1;
231
232        if count == 0 && self.control.inner.graceful.is_notified() {
233            self.control.inner.conn_end.notify_waiters();
234        }
235    }
236}
237
238#[cfg(test)]
239mod tests {
240    use super::{Control, Handle};
241    use std::{net::SocketAddr, time::Duration};
242
243    #[tokio::test]
244    async fn listening_returns_none_after_bind_failure() {
245        let handle = Handle::<SocketAddr>::new();
246
247        // This is what `Server::serve` calls when binding fails.
248        handle.notify_listening(None);
249
250        let addr = tokio::time::timeout(Duration::from_secs(1), handle.listening())
251            .await
252            .expect("listening() should resolve immediately after a bind failure");
253
254        assert_eq!(addr, None);
255    }
256
257    #[tokio::test]
258    async fn listening_returns_addr_after_successful_bind() {
259        let handle = Handle::<SocketAddr>::new();
260        let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
261
262        handle.notify_listening(Some(addr));
263
264        let resolved = tokio::time::timeout(Duration::from_secs(1), handle.listening())
265            .await
266            .expect("listening() should resolve immediately");
267
268        assert_eq!(resolved, Some(addr));
269    }
270
271    #[tokio::test]
272    async fn control_is_shared_between_handles() {
273        let control = Control::new();
274        let first = Handle::<SocketAddr>::with_control(control.clone());
275        let second = Handle::<SocketAddr>::with_control(control.clone());
276
277        assert!(std::sync::Arc::ptr_eq(
278            &first.control.inner,
279            &second.control.inner
280        ));
281        assert!(std::sync::Arc::ptr_eq(&control.inner, &first.control.inner));
282    }
283}