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 {
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<serde_json::Value>) -> Vec<FacePoint> {
points
.iter()
.filter_map(|p| {