diff --git a/crates/kumod/src/smtp_dispatcher.rs b/crates/kumod/src/smtp_dispatcher.rs index ac26dc7e..c64adb19 100644 --- a/crates/kumod/src/smtp_dispatcher.rs +++ b/crates/kumod/src/smtp_dispatcher.rs @@ -280,13 +280,17 @@ impl SmtpDispatcher { format!("Attempting connection to {address:?} port {port}") }); - let make_connection = async { + let make_connection = { let address = address.clone(); let timeouts = path_config.client_timeouts.clone(); let egress_source = dispatcher.egress_source.clone(); let tracer = self.tracer.clone(); - async move { + // We need to spawn the connection attempt into another task, + // otherwise the select! invocation below won't run it in parallel with + // awaiting the shutdown subscription, causing us to uselessly wait + // for the full connect timeout during shutdown. + tokio::spawn(async move { let (stream, source_address) = tokio::time::timeout( timeouts.connect_timeout, egress_source.connect_to(SocketAddr::new(address.addr, port)), @@ -317,15 +321,16 @@ impl SmtpDispatcher { } Ok((client, source_address)) - } + }) }; self.source_address.take(); let (mut client, source_address) = tokio::select! { - _ = shutdown.shutting_down() => anyhow::bail!("shutting down"), - result = make_connection => { result }, + _ = shutdown.shutting_down() => { + anyhow::bail!("shutting down"); + } + result = make_connection => { result? }, } - .await .with_context(|| connect_context.clone())?; self.source_address.replace(source_address); diff --git a/docs/changelog/main.md b/docs/changelog/main.md index 0955e331..b2324659 100644 --- a/docs/changelog/main.md +++ b/docs/changelog/main.md @@ -62,6 +62,9 @@ * Add `/api/check-liveness/v1` API endpoint to determine whether the KumoMTA node is live and ready to receive messages. * Updated redis crate to 0.26, which improves connection management and pooling. +* Reduced latency during shutdown. Connections that are being attempted to + unreachable destinations no longer block shutdown until they timeout, and + are instead terminated immediately. ## Fixes