feat: progressive multi-round face matching + pending person API
- Identity agent: per-face max matching, multi-round with derived seeds from high-confidence faces, angle diversity filter (cosine sim < 0.90) - Pending person API: POST /file/:file_uuid/pending-person + GET /file/:file_uuid/pending-persons with status=pending, source=manual - Update API docs (07_identity.md)
This commit is contained in:
@@ -646,6 +646,10 @@ impl JobWorker {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
crate::core::db::ProcessorType::FaceCluster => {
|
||||
info!("Face clustering processor completed for {}", job.uuid);
|
||||
Ok(())
|
||||
}
|
||||
crate::core::db::ProcessorType::Pose => {
|
||||
if let Ok(result) = serde_json::from_str::<
|
||||
crate::core::processor::PoseResult,
|
||||
@@ -1093,6 +1097,33 @@ vector,
|
||||
.filter(|r| job_processors.contains(&r.processor_type.as_str().to_string()))
|
||||
.any(|r| matches!(r.status, crate::core::db::ProcessorJobStatus::Pending));
|
||||
|
||||
const MAX_RETRIES: i32 = 3;
|
||||
|
||||
if any_failed && !any_pending {
|
||||
let failed_processors_to_retry: Vec<i32> = results
|
||||
.iter()
|
||||
.filter(|r| {
|
||||
job_processors.contains(&r.processor_type.as_str().to_string())
|
||||
&& matches!(r.status, crate::core::db::ProcessorJobStatus::Failed)
|
||||
&& r.retry_count < MAX_RETRIES
|
||||
})
|
||||
.map(|r| r.id)
|
||||
.collect();
|
||||
|
||||
if !failed_processors_to_retry.is_empty() {
|
||||
info!("🔄 Attempting to retry {} failed processors...", failed_processors_to_retry.len());
|
||||
|
||||
for result_id in failed_processors_to_retry {
|
||||
if let Ok(true) = self.db.retry_failed_processor(result_id, MAX_RETRIES).await {
|
||||
if let Ok(mut conn) = self.redis.get_conn().await {
|
||||
let redis_key = format!("momentry:progress:{}", uuid);
|
||||
let _: Result<i32, _> = redis::AsyncCommands::del(&mut conn, &redis_key).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let any_skipped = results
|
||||
.iter()
|
||||
.filter(|r| job_processors.contains(&r.processor_type.as_str().to_string()))
|
||||
|
||||
@@ -747,6 +747,27 @@ impl ProcessorPool {
|
||||
pid: 0,
|
||||
})
|
||||
}
|
||||
ProcessorType::FaceCluster => {
|
||||
let result = processor::process_face_cluster(
|
||||
video_path,
|
||||
output_path.to_str().unwrap(),
|
||||
uuid,
|
||||
Some(&sample_frames),
|
||||
)
|
||||
.await?;
|
||||
tracing::info!(
|
||||
"FACE_CLUSTER completed, output: {}",
|
||||
output_path.to_str().unwrap()
|
||||
);
|
||||
Ok(ProcessorOutput {
|
||||
data: serde_json::to_value(result)?,
|
||||
chunks_produced: 0,
|
||||
frames_processed: 0,
|
||||
total_frames: 0,
|
||||
retry_count: 0,
|
||||
pid: 0,
|
||||
})
|
||||
}
|
||||
ProcessorType::Pose => {
|
||||
let result = processor::process_pose(
|
||||
video_path,
|
||||
|
||||
Reference in New Issue
Block a user