diff --git a/server/svix-server/src/core/webhook_http_client.rs b/server/svix-server/src/core/webhook_http_client.rs index b55eed98e6..8842c70d76 100644 --- a/server/svix-server/src/core/webhook_http_client.rs +++ b/server/svix-server/src/core/webhook_http_client.rs @@ -36,7 +36,7 @@ use ipnet::IpNet; use openssl::ssl::{SslConnector, SslConnectorBuilder, SslMethod, SslVerifyMode}; use serde::Serialize; use thiserror::Error; -use tokio::{net::TcpStream, sync::Mutex}; +use tokio::{net::TcpStream, sync::OnceCell}; use tower::Service; use crate::{ @@ -561,21 +561,15 @@ type NonLocalHttpConnector = HttpConnector; /// Specific private subnets or domain names may be whitelisted. #[derive(Clone, Debug)] struct NonLocalDnsResolver { - state: Arc>, + resolver: Arc>, whitelist_nets: Arc>, whitelist_names: Arc>, } -#[derive(Clone, Debug)] -enum DnsState { - Init, - Ready(Arc), -} - impl NonLocalDnsResolver { pub fn new(whitelist_nets: Arc>, whitelist_names: Arc>) -> Self { NonLocalDnsResolver { - state: Arc::new(Mutex::new(DnsState::Init)), + resolver: Arc::new(OnceCell::new()), whitelist_nets, whitelist_names, } @@ -592,24 +586,12 @@ impl Service for NonLocalDnsResolver { } fn call(&mut self, name: Name) -> Self::Future { - let resolver = self.clone(); + let this = self.clone(); let whitelist_nets = self.whitelist_nets.clone(); let whitelist_names = self.whitelist_names.clone(); Box::pin(async move { - let mut lock = resolver.state.lock().await; - - let resolver = match &*lock { - DnsState::Init => { - let resolver = new_resolver().await?; - *lock = DnsState::Ready(resolver.clone()); - resolver - } - - DnsState::Ready(resolver) => resolver.clone(), - }; - - drop(lock); + let resolver = this.resolver.get_or_try_init(new_resolver).await?; let whitelisted_name = whitelist_names .iter() @@ -653,10 +635,15 @@ impl Iterator for SocketAddrs { } } -async fn new_resolver() -> Result, NetError> { - let mut builder = Resolver::builder_tokio()?; - builder.options_mut().ip_strategy = hickory_resolver::config::LookupIpStrategy::Ipv4thenIpv6; - Ok(Arc::new(builder.build()?)) +async fn new_resolver() -> Result { + tokio::task::spawn_blocking(|| { + let mut builder = Resolver::builder_tokio()?; + builder.options_mut().ip_strategy = + hickory_resolver::config::LookupIpStrategy::Ipv4thenIpv6; + builder.build() + }) + .await + .unwrap_or_else(|e| std::panic::resume_unwind(e.into_panic())) } fn is_allowed(addr: IpAddr) -> bool {