From 2da0ada34a6332c4ea0e7c4b71de7de00d797e59 Mon Sep 17 00:00:00 2001 From: Accusys Date: Fri, 10 Jul 2026 00:58:30 +0800 Subject: [PATCH] feat(tkg): add Qdrant retry logic with exponential backoff - scroll_face_points now retries up to 3 times on failure - Exponential backoff: 1s, 2s, 4s between attempts - Logs retry attempts for debugging - Prevents silent failures when Qdrant is temporarily unavailable --- src/core/processor/tkg.rs | 48 +++++++++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/src/core/processor/tkg.rs b/src/core/processor/tkg.rs index 05f4287..af5923f 100644 --- a/src/core/processor/tkg.rs +++ b/src/core/processor/tkg.rs @@ -34,18 +34,46 @@ async fn scroll_face_points(file_uuid: &str) -> Vec { ] }); - let points = match qdrant.scroll_all_points("_faces", filter, 500).await { - Ok(pts) => pts, - Err(e) => { - tracing::error!( - "[TKG-Qdrant] Failed to scroll _faces for {}: {}", - file_uuid, - e - ); - return vec![]; + // Retry with exponential backoff (3 attempts) + let mut last_err = None; + for attempt in 1..=3 { + match qdrant.scroll_all_points("_faces", filter.clone(), 500).await { + Ok(pts) => { + if attempt > 1 { + tracing::info!( + "[TKG-Qdrant] scroll succeeded on attempt {} for {}", + attempt, + file_uuid + ); + } + return parse_face_points(pts); + } + Err(e) => { + last_err = Some(e); + if attempt < 3 { + let delay_ms = 1000 * 2_u64.pow(attempt as u32 - 1); // 1s, 2s, 4s + tracing::warn!( + "[TKG-Qdrant] scroll attempt {} failed for {}: {} (retrying in {}ms)", + attempt, + file_uuid, + last_err.as_ref().unwrap(), + delay_ms + ); + tokio::time::sleep(std::time::Duration::from_millis(delay_ms)).await; + } + } } - }; + } + tracing::error!( + "[TKG-Qdrant] Failed to scroll _faces for {} after 3 attempts", + file_uuid + ); + vec![] +} + +/// Parse FacePoint structs from Qdrant response +fn parse_face_points(points: Vec) -> Vec { points .iter() .filter_map(|p| {