diff --git a/src/worker/job_worker.rs b/src/worker/job_worker.rs index d585e24..c3b3606 100644 --- a/src/worker/job_worker.rs +++ b/src/worker/job_worker.rs @@ -1839,54 +1839,41 @@ impl JobWorker { } // 🚀 P4 Trigger: TKG Build (Face + ASRX) → then Rule2 ingestion + // Note: build_tkg uses ON CONFLICT, so it's safe to call multiple times if has_face && has_asrx { - // Guard: only spawn TKG if nodes don't exist yet - let tkg_nodes_table = schema::table_name("tkg_nodes"); - let tkg_exists: bool = sqlx::query_scalar::<_, i32>(&format!( - "SELECT 1 FROM {tkg_nodes_table} WHERE file_uuid = $1 LIMIT 1" - )) - .bind(uuid) - .fetch_optional(self.db.pool()) - .await? - .unwrap_or(0) > 0; + info!("📝 Prerequisites met for TKG Build. Starting graph construction..."); + 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 for {}: {} nodes, {} edges", uuid_clone, total_nodes, total_edges); - if tkg_exists { - info!("✅ TKG already built for {}, skipping", uuid); - } else { - info!("📝 Prerequisites met for TKG Build. Starting graph construction..."); - 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 for {}: {} nodes, {} edges", uuid_clone, total_nodes, total_edges); + let mut pp = PipelineProgress::new(&uuid_clone); + pp.update_stage("tkg_nodes", 1.0, "completed", Some(format!("{} nodes", total_nodes))); + pp.update_stage("tkg_edges", 1.0, "completed", Some(format!("{} edges", total_edges))); + publish_pipeline_progress(redis_clone.as_ref(), &uuid_clone, &pp).await; - let mut pp = PipelineProgress::new(&uuid_clone); - pp.update_stage("tkg_nodes", 1.0, "completed", Some(format!("{} nodes", total_nodes))); - pp.update_stage("tkg_edges", 1.0, "completed", Some(format!("{} edges", total_edges))); - publish_pipeline_progress(redis_clone.as_ref(), &uuid_clone, &pp).await; - - // Trigger Rule 2 ingestion after TKG complete - if total_edges > 0 { - match crate::core::chunk::rule2_ingest::ingest_rule2(db_clone.pool(), &uuid_clone, None, None).await { - Ok(rule2_count) => { - info!("✅ Rule 2 ingestion completed for {}: {} relationship chunks", uuid_clone, rule2_count); - let mut pp = PipelineProgress::new(&uuid_clone); - pp.update_stage("rule2_ingestion", 1.0, "completed", Some(format!("{} chunks", rule2_count))); - publish_pipeline_progress(redis_clone.as_ref(), &uuid_clone, &pp).await; - } - Err(e) => error!("❌ Rule 2 ingestion failed for {}: {}", uuid_clone, e), + // Trigger Rule 2 ingestion after TKG complete + if total_edges > 0 { + match crate::core::chunk::rule2_ingest::ingest_rule2(db_clone.pool(), &uuid_clone, None, None).await { + Ok(rule2_count) => { + info!("✅ Rule 2 ingestion completed for {}: {} relationship chunks", uuid_clone, rule2_count); + let mut pp = PipelineProgress::new(&uuid_clone); + pp.update_stage("rule2_ingestion", 1.0, "completed", Some(format!("{} chunks", rule2_count))); + publish_pipeline_progress(redis_clone.as_ref(), &uuid_clone, &pp).await; } + Err(e) => error!("❌ Rule 2 ingestion failed for {}: {}", uuid_clone, e), } } - Err(e) => error!("❌ TKG build failed for {}: {}", uuid_clone, e), } - }); - } + Err(e) => error!("❌ TKG build failed for {}: {}", uuid_clone, e), + } + }); } if !Self::ingestion_complete(self.db.pool(), uuid, job_processors).await {