diff --git a/src/worker/job_worker.rs b/src/worker/job_worker.rs index ef41a67..b474ce9 100644 --- a/src/worker/job_worker.rs +++ b/src/worker/job_worker.rs @@ -2102,29 +2102,53 @@ impl JobWorker { if tkg_done { info!("✅ TKG already built for {}, skipping spawn", uuid); } else { - // Check if face_traced.json exists (store_traced_faces.py completed) - let traced_path = format!( - "{}{}.face_traced.json", + // Check face.json status first + let face_json_path = format!( + "{}{}.face.json", crate::core::config::OUTPUT_DIR.as_str().trim_end_matches('/'), uuid ); - if !std::path::Path::new(&traced_path).exists() { - info!( - "⏳ TKG build waiting for face_traced.json: {} (file_uuid={})", - traced_path, uuid - ); - // Don't spawn TKG yet, wait for next poll + let has_faces = if std::path::Path::new(&face_json_path).exists() { + if let Ok(content) = std::fs::read_to_string(&face_json_path) { + if let Ok(face_data) = serde_json::from_str::(&content) { + face_data.get("status") + .and_then(|s| s.as_str()) + .map(|s| s == "has_faces") + .unwrap_or(false) + } else { + false + } + } else { + false + } } else { - info!( - "📝 Prerequisites met for TKG Build (face_traced.json exists): {}", + false + }; + + if has_faces { + // Has faces - wait for face_traced.json + let traced_path = format!( + "{}{}.face_traced.json", + crate::core::config::OUTPUT_DIR.as_str().trim_end_matches('/'), uuid ); - let db_clone = self.db.clone(); - let redis_clone = self.redis.clone(); - let uuid_clone = uuid.to_string(); - let output_dir_clone = crate::core::config::OUTPUT_DIR.clone(); - tokio::spawn(async move { + + if !std::path::Path::new(&traced_path).exists() { + info!( + "⏳ TKG build waiting for face_traced.json: {} (file_uuid={})", + traced_path, uuid + ); + } else { + info!( + "📝 Prerequisites met for TKG Build (face_traced.json exists): {}", + uuid + ); + let db_clone = self.db.clone(); + let redis_clone = self.redis.clone(); + let uuid_clone = uuid.to_string(); + let output_dir_clone = crate::core::config::OUTPUT_DIR.clone(); + tokio::spawn(async move { match crate::core::processor::tkg::build_tkg( &db_clone, &uuid_clone, @@ -2209,6 +2233,52 @@ impl JobWorker { } }); } + } else { + // No faces detected - spawn TKG without waiting for face_traced.json + info!( + "📝 TKG Build proceeding without face_traced.json (no faces detected): {}", + uuid + ); + let db_clone = self.db.clone(); + let redis_clone = self.redis.clone(); + let uuid_clone = uuid.to_string(); + let output_dir_clone = crate::core::config::OUTPUT_DIR.clone(); + tokio::spawn(async move { + match crate::core::processor::tkg::build_tkg( + &db_clone, + &uuid_clone, + &output_dir_clone, + Some(redis_clone.clone()), + ) + .await + { + Ok(r) => { + let total_nodes = r.face_track_nodes + + r.gaze_track_nodes + + r.lip_track_nodes + + r.text_region_nodes + + r.appearance_trace_nodes + + r.accessory_nodes + + r.object_nodes + + r.hand_nodes + + r.speaker_nodes; + let total_edges = r.co_occurrence_edges + + r.speaker_face_edges + + r.face_face_edges + + r.mutual_gaze_edges + + r.lip_sync_edges + + r.has_appearance_edges + + r.wears_edges + + r.hand_object_edges; + info!( + "✅ TKG build completed (no faces) for {}: {} nodes, {} edges", + uuid_clone, total_nodes, total_edges + ); + } + Err(e) => error!("❌ TKG build failed for {}: {}", uuid_clone, e), + } + }); + } } }