From 1331134c98ca0c6eec8853059b26aa7530392ffd Mon Sep 17 00:00:00 2001 From: Baby Bear <132609968+smallbabybear@users.noreply.github.com> Date: Thu, 30 Oct 2025 02:00:37 +0700 Subject: [PATCH] Retry 502 error --- client-sdk/src/external_api/utils/query.rs | 43 ++++++++++++++++++++-- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/client-sdk/src/external_api/utils/query.rs b/client-sdk/src/external_api/utils/query.rs index ac9c49cd..e76df5e9 100644 --- a/client-sdk/src/external_api/utils/query.rs +++ b/client-sdk/src/external_api/utils/query.rs @@ -4,7 +4,7 @@ use intmax2_interfaces::api::error::ServerError; use reqwest::{header, Client, Response, Url}; use serde::{de::DeserializeOwned, Deserialize, Serialize}; -use crate::external_api::utils::retry::with_retry; +use crate::external_api::utils::{retry::with_retry, time::sleep_for}; /// Timeout for reqwest requests. /// Because WASM only accepts timeout in the request builder, not the client builder, @@ -13,6 +13,8 @@ pub const REQWEST_TIMEOUT: Duration = Duration::from_secs(30); /// Maximum response body size for logging (in characters) const MAX_RESPONSE_LOG_SIZE: usize = 500; +const DEFAULT_BAD_GATEWAY_RETRIES: u32 = 1; +const DEFAULT_BAD_GATEWAY_RETRY_DELAY_SECS: u64 = 30; #[derive(Debug, Deserialize)] struct ErrorResponse { @@ -133,9 +135,42 @@ fn serialize_body_for_logging(body: Option<&B>) -> Result Result { - with_retry(|| async { request_builder.try_clone().unwrap().send().await }) - .await - .map_err(|e| ServerError::NetworkError(e.to_string())) + let max_502_retries: u32 = std::env::var("BAD_GATEWAY_RETRY_LIMIT") + .ok() + .and_then(|v| v.parse::().ok()) + .unwrap_or(DEFAULT_BAD_GATEWAY_RETRIES); + + let retry_delay_secs: u64 = std::env::var("BAD_GATEWAY_RETRY_DELAY_SECS") + .ok() + .and_then(|v| v.parse::().ok()) + .unwrap_or(DEFAULT_BAD_GATEWAY_RETRY_DELAY_SECS); + + let mut bad_gateway_retries: u32 = 0; + + loop { + let response = with_retry(|| async { request_builder.try_clone().unwrap().send().await }) + .await + .map_err(|e| ServerError::NetworkError(e.to_string()))?; + + let status = response.status().as_u16(); + + if status != 502 { + return Ok(response); + } + + if bad_gateway_retries >= max_502_retries { + return Ok(response); + } + + log::warn!( + "Received 502 Bad Gateway from upstream. Waiting {delay}s before retry (attempt {}/{})", + bad_gateway_retries + 1, + max_502_retries, + delay = retry_delay_secs + ); + sleep_for(retry_delay_secs).await; + bad_gateway_retries += 1; + } } /// Handles HTTP response, including error cases and deserialization