From ff47bffe0c4753834c3d48ee627cd0861c447651 Mon Sep 17 00:00:00 2001 From: asepharyana Date: Sat, 18 Jul 2026 02:57:18 +0700 Subject: [PATCH] refactor: reuse is_auth_error from provider.rs, DRY backend retry logic --- crates/zesdex-backend/src/app/subagent/engine.rs | 11 ++--------- crates/zesdex-backend/src/app/workflow/engine/mod.rs | 4 +--- crates/zesdex-backend/src/service/provider.rs | 2 +- 3 files changed, 4 insertions(+), 13 deletions(-) diff --git a/crates/zesdex-backend/src/app/subagent/engine.rs b/crates/zesdex-backend/src/app/subagent/engine.rs index a2fcf8d..cac5e66 100644 --- a/crates/zesdex-backend/src/app/subagent/engine.rs +++ b/crates/zesdex-backend/src/app/subagent/engine.rs @@ -25,19 +25,12 @@ fn step_retry_delay(attempt: u32) -> Duration { /// Heuristic to decide whether the error is worth retrying. fn should_retry_subagent_step(err_str: &str) -> bool { - let lower = err_str.to_lowercase(); // Never retry auth/billing failures - if err_str.contains("API error 401") - || err_str.contains("API error 402") - || err_str.contains("API error 403") - || lower.contains("unauthorized") - || lower.contains("forbidden") - || lower.contains("authentication failed") - { + if crate::service::provider::is_auth_error(err_str) { return false; } // Never retry abort or user cancellation - if lower.contains("aborted") { + if err_str.to_lowercase().contains("aborted") { return false; } // Everything else (timeout, 5xx, rate-limit, network blip) is retryable diff --git a/crates/zesdex-backend/src/app/workflow/engine/mod.rs b/crates/zesdex-backend/src/app/workflow/engine/mod.rs index 2f97979..b882c72 100644 --- a/crates/zesdex-backend/src/app/workflow/engine/mod.rs +++ b/crates/zesdex-backend/src/app/workflow/engine/mod.rs @@ -421,9 +421,7 @@ fn spawn_single_agent(sp: SpawnCtx<'_>) -> anyhow::Result { } Err(e) => { let err_str = e.to_string(); - let is_auth = err_str.contains("API error 401") - || err_str.contains("API error 402") - || err_str.contains("API error 403"); + let is_auth = crate::service::provider::is_auth_error(&err_str); // Auth errors are permanent — don't retry. if is_auth || attempt >= 2 { let _ = done_tx.send(Err(e)); diff --git a/crates/zesdex-backend/src/service/provider.rs b/crates/zesdex-backend/src/service/provider.rs index f5e138a..5722d99 100644 --- a/crates/zesdex-backend/src/service/provider.rs +++ b/crates/zesdex-backend/src/service/provider.rs @@ -57,7 +57,7 @@ fn backoff_duration(attempt: u32) -> Duration { /// request builders below, plus well-known auth keywords in case the body /// contains them. This is intentionally tighter than `contains("401")`, /// which could false-positive on a URL port, model name, or body text. -fn is_auth_error(err_str: &str) -> bool { +pub fn is_auth_error(err_str: &str) -> bool { let err_lower = err_str.to_lowercase(); // Structured HTTP status patterns (err_str.contains("API error 401")