mirror of
https://github.com/tokio-rs/axum.git
synced 2026-08-24 00:00:16 +02:00
Split up serve functions for Serve and WithGracefulShutdown again
We should not spawn a tokio task to wait on a signal that can never arrive.
This commit is contained in:
+80
-47
@@ -166,6 +166,33 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "tokio", any(feature = "http1", feature = "http2")))]
|
||||||
|
impl<L, M, S> Serve<L, M, S>
|
||||||
|
where
|
||||||
|
L: Listener,
|
||||||
|
L::Addr: Debug,
|
||||||
|
M: for<'a> Service<IncomingStream<'a, L>, Error = Infallible, Response = S> + Send + 'static,
|
||||||
|
for<'a> <M as Service<IncomingStream<'a, L>>>::Future: Send,
|
||||||
|
S: Service<Request, Response = Response, Error = Infallible> + Clone + Send + 'static,
|
||||||
|
S::Future: Send,
|
||||||
|
{
|
||||||
|
async fn run(self) -> ! {
|
||||||
|
let Self {
|
||||||
|
mut listener,
|
||||||
|
mut make_service,
|
||||||
|
_marker,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
let (signal_tx, _signal_rx) = watch::channel(());
|
||||||
|
let (_close_tx, close_rx) = watch::channel(());
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let (io, remote_addr) = listener.accept().await;
|
||||||
|
handle_connection(&mut make_service, &signal_tx, &close_rx, io, remote_addr).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "tokio", any(feature = "http1", feature = "http2")))]
|
#[cfg(all(feature = "tokio", any(feature = "http1", feature = "http2")))]
|
||||||
impl<L, M, S> Debug for Serve<L, M, S>
|
impl<L, M, S> Debug for Serve<L, M, S>
|
||||||
where
|
where
|
||||||
@@ -201,10 +228,7 @@ where
|
|||||||
type IntoFuture = private::ServeFuture;
|
type IntoFuture = private::ServeFuture;
|
||||||
|
|
||||||
fn into_future(self) -> Self::IntoFuture {
|
fn into_future(self) -> Self::IntoFuture {
|
||||||
private::ServeFuture(Box::pin(async move {
|
private::ServeFuture(Box::pin(async move { self.run().await }))
|
||||||
do_serve(self.listener, self.make_service, std::future::pending()).await;
|
|
||||||
Ok(())
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,6 +253,57 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "tokio", any(feature = "http1", feature = "http2")))]
|
||||||
|
impl<L, M, S, F> WithGracefulShutdown<L, M, S, F>
|
||||||
|
where
|
||||||
|
L: Listener,
|
||||||
|
L::Addr: Debug,
|
||||||
|
M: for<'a> Service<IncomingStream<'a, L>, Error = Infallible, Response = S> + Send + 'static,
|
||||||
|
for<'a> <M as Service<IncomingStream<'a, L>>>::Future: Send,
|
||||||
|
S: Service<Request, Response = Response, Error = Infallible> + Clone + Send + 'static,
|
||||||
|
S::Future: Send,
|
||||||
|
F: Future<Output = ()> + Send + 'static,
|
||||||
|
{
|
||||||
|
async fn run(self) {
|
||||||
|
let Self {
|
||||||
|
mut listener,
|
||||||
|
mut make_service,
|
||||||
|
signal,
|
||||||
|
_marker,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
let (signal_tx, signal_rx) = watch::channel(());
|
||||||
|
tokio::spawn(async move {
|
||||||
|
signal.await;
|
||||||
|
trace!("received graceful shutdown signal. Telling tasks to shutdown");
|
||||||
|
drop(signal_rx);
|
||||||
|
});
|
||||||
|
|
||||||
|
let (close_tx, close_rx) = watch::channel(());
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let (io, remote_addr) = tokio::select! {
|
||||||
|
conn = listener.accept() => conn,
|
||||||
|
_ = signal_tx.closed() => {
|
||||||
|
trace!("signal received, not accepting new connections");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
handle_connection(&mut make_service, &signal_tx, &close_rx, io, remote_addr).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
drop(close_rx);
|
||||||
|
drop(listener);
|
||||||
|
|
||||||
|
trace!(
|
||||||
|
"waiting for {} task(s) to finish",
|
||||||
|
close_tx.receiver_count()
|
||||||
|
);
|
||||||
|
close_tx.closed().await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "tokio", any(feature = "http1", feature = "http2")))]
|
#[cfg(all(feature = "tokio", any(feature = "http1", feature = "http2")))]
|
||||||
impl<L, M, S, F> Debug for WithGracefulShutdown<L, M, S, F>
|
impl<L, M, S, F> Debug for WithGracefulShutdown<L, M, S, F>
|
||||||
where
|
where
|
||||||
@@ -269,54 +344,12 @@ where
|
|||||||
|
|
||||||
fn into_future(self) -> Self::IntoFuture {
|
fn into_future(self) -> Self::IntoFuture {
|
||||||
private::ServeFuture(Box::pin(async move {
|
private::ServeFuture(Box::pin(async move {
|
||||||
do_serve(self.listener, self.make_service, self.signal).await;
|
self.run().await;
|
||||||
Ok(())
|
Ok(())
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "tokio", any(feature = "http1", feature = "http2")))]
|
|
||||||
async fn do_serve<L, M, F, S>(mut listener: L, mut make_service: M, signal: F)
|
|
||||||
where
|
|
||||||
L: Listener,
|
|
||||||
L::Addr: Debug,
|
|
||||||
M: for<'a> Service<IncomingStream<'a, L>, Error = Infallible, Response = S> + Send + 'static,
|
|
||||||
for<'a> <M as Service<IncomingStream<'a, L>>>::Future: Send,
|
|
||||||
S: Service<Request, Response = Response, Error = Infallible> + Clone + Send + 'static,
|
|
||||||
S::Future: Send,
|
|
||||||
F: Future<Output = ()> + Send + 'static,
|
|
||||||
{
|
|
||||||
let (signal_tx, signal_rx) = watch::channel(());
|
|
||||||
tokio::spawn(async move {
|
|
||||||
signal.await;
|
|
||||||
trace!("received graceful shutdown signal. Telling tasks to shutdown");
|
|
||||||
drop(signal_rx);
|
|
||||||
});
|
|
||||||
|
|
||||||
let (close_tx, close_rx) = watch::channel(());
|
|
||||||
|
|
||||||
loop {
|
|
||||||
let (io, remote_addr) = tokio::select! {
|
|
||||||
conn = listener.accept() => conn,
|
|
||||||
_ = signal_tx.closed() => {
|
|
||||||
trace!("signal received, not accepting new connections");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
handle_connection(&mut make_service, &signal_tx, &close_rx, io, remote_addr).await;
|
|
||||||
}
|
|
||||||
|
|
||||||
drop(close_rx);
|
|
||||||
drop(listener);
|
|
||||||
|
|
||||||
trace!(
|
|
||||||
"waiting for {} task(s) to finish",
|
|
||||||
close_tx.receiver_count()
|
|
||||||
);
|
|
||||||
close_tx.closed().await;
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn handle_connection<L, M, S>(
|
async fn handle_connection<L, M, S>(
|
||||||
make_service: &mut M,
|
make_service: &mut M,
|
||||||
signal_tx: &watch::Sender<()>,
|
signal_tx: &watch::Sender<()>,
|
||||||
|
|||||||
Reference in New Issue
Block a user