diff --git a/src/lib.rs b/src/lib.rs index b49e7e3..6abb287 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -284,10 +284,29 @@ impl Server { } } - /// Serves a single HTTP connection from a hyper service backend - async fn serve_connection( + /// Serves a single HTTP connection from a hyper service backend. + /// + /// This method handles an individual HTTP connection, processing requests through + /// the provided service and managing the connection lifecycle. + /// + /// # Type Parameters + /// + /// * `B`: The body type for the HTTP response. + /// * `IO`: The I/O type for the HTTP connection. + /// * `S`: The service type that processes HTTP requests. + /// * `E`: The executor type for the HTTP server connection. + /// + /// # Parameters + /// + /// * `hyper_io`: The I/O object representing the inbound hyper IO stream. + /// * `hyper_svc`: The hyper `Service` implementation used to process HTTP requests. + /// * `builder`: An `HttpConnBuilder` used to create and serve the HTTP connection. + /// * `watcher`: An optional `tokio::sync::watch::Receiver` for graceful shutdown signaling. + /// * `max_connection_age`: An optional `Duration` specifying the maximum age of the connection + /// before initiating a graceful shutdown. + async fn serve_http_connection( hyper_io: IO, - hyper_svc: S, + hyper_service: S, builder: HttpConnBuilder, mut watcher: Option>, max_connection_age: Option, @@ -296,43 +315,55 @@ impl Server { B::Data: Send, B::Error: Into> + Send + Sync, IO: hyper::rt::Read + hyper::rt::Write + Unpin + Send + 'static, - S: HyperService, Response = Response> + Clone + Send + 'static, + S: HyperService, Response=Response> + Clone + Send + 'static, S::Future: Send + 'static, S::Error: Into> + Send, E: HttpServerConnExec + Send + Sync + 'static, { + // Spawn a new asynchronous task to handle the incoming hyper IO stream tokio::spawn(async move { { + // Set up a fused future for the watcher let mut sig = pin!(Fuse { - inner: watcher.as_mut().map(|w| w.changed()), - }); + inner: watcher.as_mut().map(|w| w.changed()), + }); - let mut conn = pin!(builder.serve_connection(hyper_io, hyper_svc)); + // Create and pin the HTTP connection + let mut conn = pin!(builder.serve_connection(hyper_io, hyper_service)); + // Set up the sleep future for max connection age let sleep = sleep_or_pending(max_connection_age); tokio::pin!(sleep); + // Main loop for serving the HTTP connection loop { tokio::select! { - rv = &mut conn => { - if let Err(err) = rv { - debug!("failed serving connection: {:#}", err); - } - break; - }, - _ = &mut sleep => { - conn.as_mut().graceful_shutdown(); - sleep.set(sleep_or_pending(None)); - }, - _ = &mut sig => { - conn.as_mut().graceful_shutdown(); + // Handle the connection result + rv = &mut conn => { + if let Err(err) = rv { + // Log any errors that occur while serving the HTTP connection + debug!("failed serving HTTP connection: {:#}", err); } + break; + }, + // Handle max connection age timeout + _ = &mut sleep => { + // Initiate a graceful shutdown when max connection age is reached + conn.as_mut().graceful_shutdown(); + sleep.set(sleep_or_pending(None)); + }, + // Handle graceful shutdown signal + _ = &mut sig => { + // Initiate a graceful shutdown when signal is received + conn.as_mut().graceful_shutdown(); } } + } } + // Clean up and log connection closure drop(watcher); - trace!("connection closed"); + trace!("HTTP connection closed"); }); } }