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
This commit is contained in:
Accusys
2026-07-10 00:58:30 +08:00
parent 13abb15595
commit 2da0ada34a
+38 -10
View File
@@ -34,18 +34,46 @@ async fn scroll_face_points(file_uuid: &str) -> Vec<FacePoint> {
] ]
}); });
let points = match qdrant.scroll_all_points("_faces", filter, 500).await { // Retry with exponential backoff (3 attempts)
Ok(pts) => pts, let mut last_err = None;
Err(e) => { for attempt in 1..=3 {
tracing::error!( match qdrant.scroll_all_points("_faces", filter.clone(), 500).await {
"[TKG-Qdrant] Failed to scroll _faces for {}: {}", Ok(pts) => {
file_uuid, if attempt > 1 {
e tracing::info!(
); "[TKG-Qdrant] scroll succeeded on attempt {} for {}",
return vec![]; 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<serde_json::Value>) -> Vec<FacePoint> {
points points
.iter() .iter()
.filter_map(|p| { .filter_map(|p| {