From 4aa6dbb5a701377d9c3b4072f4066532d9888586 Mon Sep 17 00:00:00 2001 From: picoHz <53327867+picoHz@users.noreply.github.com> Date: Sun, 10 Sep 2023 19:24:15 +0900 Subject: [PATCH] acme: request an order on background --- taxy/src/command.rs | 14 ++++++-- taxy/src/server/state.rs | 72 +++++++++++++++++++++++++--------------- 2 files changed, 57 insertions(+), 29 deletions(-) diff --git a/taxy/src/command.rs b/taxy/src/command.rs index 0ee95548..c0972553 100644 --- a/taxy/src/command.rs +++ b/taxy/src/command.rs @@ -1,4 +1,7 @@ -use crate::{certs::Cert, server::rpc::ErasedRpcMethod}; +use crate::{ + certs::{acme::AcmeOrder, Cert}, + server::rpc::ErasedRpcMethod, +}; use std::sync::Arc; pub enum ServerCommand { @@ -8,7 +11,9 @@ pub enum ServerCommand { SetBroadcastEvents { enabled: bool, }, - StopHttpChallenges, + SetHttpChallenges { + orders: Vec, + }, CallMethod { id: usize, arg: Box, @@ -23,7 +28,10 @@ impl std::fmt::Debug for ServerCommand { .debug_struct("SetBroadcastEvents") .field("enabled", enabled) .finish(), - Self::StopHttpChallenges => f.debug_struct("StopHttpChallenges").finish(), + Self::SetHttpChallenges { orders } => f + .debug_struct("SetHttpChallenges") + .field("orders", &orders.len()) + .finish(), Self::CallMethod { id, .. } => f.debug_struct("CallMethod").field("id", id).finish(), } } diff --git a/taxy/src/server/state.rs b/taxy/src/server/state.rs index 38679d41..03b247e0 100644 --- a/taxy/src/server/state.rs +++ b/taxy/src/server/state.rs @@ -2,6 +2,7 @@ use super::acme_list::AcmeList; use super::cert_list::CertList; use super::proxy_list::ProxyList; use super::{listener::TcpListenerPool, port_list::PortList, rpc::RpcCallback}; +use crate::certs::acme::AcmeOrder; use crate::config::storage::Storage; use crate::log::DatabaseLayer; use crate::{ @@ -109,10 +110,12 @@ impl ServerState { ServerCommand::SetBroadcastEvents { enabled } => { self.broadcast_events = enabled; } - ServerCommand::StopHttpChallenges => { - self.pool.set_http_challenge_addr(None); - self.http_challenges.clear(); - self.pool.update(self.ports.as_mut_slice()).await; + ServerCommand::SetHttpChallenges { orders } => { + if orders.is_empty() { + self.stop_http_challenges().await; + } else { + self.continue_http_challenges(orders).await; + } } ServerCommand::CallMethod { id, mut arg } => { let result = arg.call(self).await; @@ -332,7 +335,7 @@ impl ServerState { } async fn start_http_challenges(&mut self) { - let entries = self.acmes.entries(); + let entries = self.acmes.entries().cloned(); let entries = entries .filter(|entry| { entry.acme.config.active @@ -358,25 +361,40 @@ impl ServerState { return; } - let mut requests = Vec::new(); - for entry in entries { - let span = span!(Level::INFO, "acme", resource_id = entry.id.to_string()); - span.in_scope(|| { - info!( - provider = entry.acme.config.provider, - identifiers = ?entry.acme.identifiers, - "starting acme request" - ); - }); - match entry.request().instrument(span.clone()).await { - Ok(request) => requests.push(request), - Err(err) => { - let _enter = span.enter(); - error!("failed to request challenge: {}", err) + let command = self.command_sender.clone(); + tokio::task::spawn(async move { + let mut orders = Vec::new(); + for entry in entries { + let span = span!(Level::INFO, "acme", resource_id = entry.id.to_string()); + span.in_scope(|| { + info!( + provider = entry.acme.config.provider, + identifiers = ?entry.acme.identifiers, + "starting acme request" + ); + }); + match entry.request().instrument(span.clone()).await { + Ok(request) => orders.push(request), + Err(err) => { + let _enter = span.enter(); + error!("failed to request challenge: {}", err) + } } } - } - let challenges = requests + let _ = command + .send(ServerCommand::SetHttpChallenges { orders }) + .await; + }); + } + + async fn stop_http_challenges(&mut self) { + self.http_challenges.clear(); + self.pool.set_http_challenge_addr(None); + self.pool.update(self.ports.as_mut_slice()).await; + } + + async fn continue_http_challenges(&mut self, orders: Vec) { + let challenges = orders .iter() .flat_map(|req| req.http_challenges.clone()) .collect(); @@ -388,9 +406,9 @@ impl ServerState { let command = self.command_sender.clone(); tokio::task::spawn(async move { - for mut req in requests { - let span = span!(Level::INFO, "acme", resource_id = req.id.to_string()); - match req.start_challenge().instrument(span.clone()).await { + for mut order in orders { + let span = span!(Level::INFO, "acme", resource_id = order.id.to_string()); + match order.start_challenge().instrument(span.clone()).await { Ok(cert) => { span.in_scope(|| { info!(id = cert.id().to_string(), "acme request completed"); @@ -407,7 +425,9 @@ impl ServerState { } } } - let _ = command.send(ServerCommand::StopHttpChallenges).await; + let _ = command + .send(ServerCommand::SetHttpChallenges { orders: vec![] }) + .await; }); }