release: v1.3.0 - TKG node type renaming
Changes: - Rust: face_trace → face_track (45 occurrences in 8 files) - Rust: gaze_trace → gaze_track, lip_trace → lip_track - Python: tkg_builder.py unified + pipeline_checklist.py fixed - Swift: swift_hand.swift hand state detection (empty vs holding) Node type changes: face_trace → face_track person_trace → body_track gaze_trace → gaze_track lip_trace → lip_track hand_trace → hand_track speaker → speaker_segment object → detected_object text_trace → text_region Migration: PUBLIC schema: 12970 + 892 + 305 rows updated
This commit is contained in:
+80
-35
@@ -743,7 +743,9 @@ impl JobWorker {
|
||||
continue;
|
||||
}
|
||||
ProcessorJobStatus::Failed => {
|
||||
if result.retry_count >= 3 {
|
||||
if result.retry_count >= 3
|
||||
&& !crate::core::config::processor::FORCE_RETRY.clone()
|
||||
{
|
||||
info!(
|
||||
"Processor {} failed {} times, max retries reached (3), skipping",
|
||||
processor_type.as_str(),
|
||||
@@ -752,11 +754,19 @@ impl JobWorker {
|
||||
started_count += 1;
|
||||
continue;
|
||||
}
|
||||
info!(
|
||||
"Processor {} previously failed (retry {}/3), retrying",
|
||||
if crate::core::config::processor::FORCE_RETRY.clone() {
|
||||
info!(
|
||||
"Processor {} previously failed (retry {}), FORCE_RETRY enabled, retrying",
|
||||
processor_type.as_str(),
|
||||
result.retry_count + 1
|
||||
result.retry_count
|
||||
);
|
||||
} else {
|
||||
info!(
|
||||
"Processor {} previously failed (retry {}/3), retrying",
|
||||
processor_type.as_str(),
|
||||
result.retry_count + 1
|
||||
);
|
||||
}
|
||||
let _ = sqlx::query(&format!(
|
||||
"UPDATE {} SET retry_count = retry_count + 1 WHERE job_id = $1 AND processor = $2",
|
||||
schema::table_name("processor_results")
|
||||
@@ -988,17 +998,6 @@ impl JobWorker {
|
||||
let chunk_t = schema::table_name("chunk");
|
||||
let fd_t = schema::table_name("face_detections");
|
||||
|
||||
macro_rules! check {
|
||||
($sql:expr) => {
|
||||
sqlx::query_scalar::<_, i32>($sql)
|
||||
.fetch_one(pool)
|
||||
.await
|
||||
.unwrap_or(0)
|
||||
> 0
|
||||
};
|
||||
}
|
||||
|
||||
let fu = uuid;
|
||||
// Only check conditions relevant to the job's processors
|
||||
let has_asr_or_asrx =
|
||||
job_processors.is_empty() || job_processors.iter().any(|p| p == "asrx" || p == "asr");
|
||||
@@ -1006,21 +1005,57 @@ impl JobWorker {
|
||||
let has_face = job_processors.is_empty() || job_processors.iter().any(|p| p == "face");
|
||||
|
||||
let rule1 = !has_asr_or_asrx
|
||||
|| check!(&format!(
|
||||
"SELECT 1 FROM {chunk_t} WHERE file_uuid = '{fu}' AND chunk_type = 'sentence' LIMIT 1"
|
||||
));
|
||||
|| sqlx::query_scalar::<_, i32>(&format!(
|
||||
"SELECT 1 FROM {chunk_t} WHERE file_uuid = $1 AND chunk_type = 'sentence' LIMIT 1"
|
||||
))
|
||||
.bind(uuid)
|
||||
.fetch_optional(pool)
|
||||
.await
|
||||
.unwrap_or(None)
|
||||
.unwrap_or(0)
|
||||
> 0;
|
||||
|
||||
let vector = !has_asr_or_asrx
|
||||
|| check!(&format!("SELECT 1 FROM {chunk_t} WHERE file_uuid = '{fu}' AND chunk_type = 'sentence' AND embedding IS NOT NULL LIMIT 1"));
|
||||
|| sqlx::query_scalar::<_, i32>(&format!(
|
||||
"SELECT 1 FROM {chunk_t} WHERE file_uuid = $1 AND chunk_type = 'sentence' AND embedding IS NOT NULL LIMIT 1"
|
||||
))
|
||||
.bind(uuid)
|
||||
.fetch_optional(pool)
|
||||
.await
|
||||
.unwrap_or(None)
|
||||
.unwrap_or(0)
|
||||
> 0;
|
||||
|
||||
let rule3 = !has_cut
|
||||
|| check!(&format!(
|
||||
"SELECT 1 FROM {chunk_t} WHERE file_uuid = '{fu}' AND chunk_type = 'cut' LIMIT 1"
|
||||
));
|
||||
|| sqlx::query_scalar::<_, i32>(&format!(
|
||||
"SELECT 1 FROM {chunk_t} WHERE file_uuid = $1 AND chunk_type = 'cut' LIMIT 1"
|
||||
))
|
||||
.bind(uuid)
|
||||
.fetch_optional(pool)
|
||||
.await
|
||||
.unwrap_or(None)
|
||||
.unwrap_or(0)
|
||||
> 0;
|
||||
|
||||
let trace = !has_face
|
||||
|| check!(&format!("SELECT COUNT(DISTINCT trace_id) FROM {fd_t} WHERE file_uuid = '{fu}' AND trace_id IS NOT NULL"));
|
||||
|| sqlx::query_scalar::<_, i64>(&format!(
|
||||
"SELECT COUNT(DISTINCT trace_id) FROM {fd_t} WHERE file_uuid = $1 AND trace_id IS NOT NULL"
|
||||
))
|
||||
.bind(uuid)
|
||||
.fetch_one(pool)
|
||||
.await
|
||||
.unwrap_or(0)
|
||||
> 0;
|
||||
|
||||
let all_ok = rule1 && vector && rule3 && trace;
|
||||
if !all_ok {
|
||||
tracing::info!(
|
||||
"[Ingestion] waiting (uuid={fu}): rule1={rule1} vector={vector} rule3={rule3} trace={trace}"
|
||||
"[Ingestion] waiting (uuid={}): rule1={} vector={} rule3={} trace={}",
|
||||
uuid,
|
||||
rule1,
|
||||
vector,
|
||||
rule3,
|
||||
trace
|
||||
);
|
||||
}
|
||||
all_ok
|
||||
@@ -1057,18 +1092,22 @@ impl JobWorker {
|
||||
|
||||
let all_completed = results
|
||||
.iter()
|
||||
.filter(|r| job_processors.contains(&r.processor_type.as_str().to_string()))
|
||||
.all(|r| matches!(r.status, crate::core::db::ProcessorJobStatus::Completed));
|
||||
|
||||
let any_failed = results
|
||||
.iter()
|
||||
.filter(|r| job_processors.contains(&r.processor_type.as_str().to_string()))
|
||||
.any(|r| matches!(r.status, crate::core::db::ProcessorJobStatus::Failed));
|
||||
|
||||
let any_pending = results
|
||||
.iter()
|
||||
.filter(|r| job_processors.contains(&r.processor_type.as_str().to_string()))
|
||||
.any(|r| matches!(r.status, crate::core::db::ProcessorJobStatus::Pending));
|
||||
|
||||
let any_skipped = results
|
||||
.iter()
|
||||
.filter(|r| job_processors.contains(&r.processor_type.as_str().to_string()))
|
||||
.any(|r| matches!(r.status, crate::core::db::ProcessorJobStatus::Skipped));
|
||||
|
||||
let completed_count = results
|
||||
@@ -1101,7 +1140,9 @@ impl JobWorker {
|
||||
.map(|r| r.processor_type.as_str().to_string())
|
||||
.collect();
|
||||
|
||||
let has_asrx = completed_processors.iter().any(|p| p == "asrx");
|
||||
let has_asr_or_asrx = completed_processors
|
||||
.iter()
|
||||
.any(|p| p == "asrx" || p == "asr");
|
||||
let has_cut = completed_processors.iter().any(|p| p == "cut");
|
||||
let has_face = completed_processors.iter().any(|p| p == "face");
|
||||
let has_yolo = completed_processors.iter().any(|p| p == "yolo");
|
||||
@@ -1110,7 +1151,7 @@ impl JobWorker {
|
||||
.update_job_processors_arrays(job_id, completed_processors, failed_processors.clone())
|
||||
.await?;
|
||||
|
||||
if has_asrx {
|
||||
if has_asr_or_asrx {
|
||||
// Guard: only spawn Rule 1 if sentence chunks don't exist yet
|
||||
let chunk_t = schema::table_name("chunk");
|
||||
let already_spawned: bool = sqlx::query_scalar::<_, i32>(&format!(
|
||||
@@ -1321,7 +1362,7 @@ impl JobWorker {
|
||||
}
|
||||
|
||||
// 🚀 P3 Trigger: Identity Agent (Face + ASRX)
|
||||
if has_face && has_asrx {
|
||||
if has_face && has_asr_or_asrx {
|
||||
info!("📝 Prerequisites met for Identity Agent. Starting analysis...");
|
||||
let db_clone = self.db.clone();
|
||||
let uuid_clone = uuid.to_string();
|
||||
@@ -1513,21 +1554,22 @@ impl JobWorker {
|
||||
let pool = db.pool();
|
||||
|
||||
let chunk_table = schema::table_name("chunk");
|
||||
let rows = sqlx::query_as::<_, (String, String, i64, i64, f64, f64)>(
|
||||
&format!(
|
||||
"SELECT chunk_id, text_content, start_frame, end_frame, start_time, end_time \
|
||||
let rows = sqlx::query_as::<_, (String, String, i64, i64, f64, f64)>(&format!(
|
||||
"SELECT chunk_id, text_content, start_frame, end_frame, start_time, end_time \
|
||||
FROM {} WHERE file_uuid = $1 AND chunk_type = 'relationship' \
|
||||
AND embedding IS NULL AND (text_content IS NOT NULL AND text_content != '') \
|
||||
ORDER BY id",
|
||||
chunk_table
|
||||
),
|
||||
)
|
||||
chunk_table
|
||||
))
|
||||
.bind(uuid)
|
||||
.fetch_all(pool)
|
||||
.await?;
|
||||
|
||||
if rows.is_empty() {
|
||||
info!("[Vectorize-R2] No relationship chunks to vectorize for {}", uuid);
|
||||
info!(
|
||||
"[Vectorize-R2] No relationship chunks to vectorize for {}",
|
||||
uuid
|
||||
);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@@ -1560,7 +1602,10 @@ impl JobWorker {
|
||||
text: Some(text.clone()),
|
||||
};
|
||||
if let Err(e) = qdrant.upsert_vector(&chunk_id, &vector, payload).await {
|
||||
error!("[Vectorize-R2] Qdrant upsert failed for {}: {}", chunk_id, e);
|
||||
error!(
|
||||
"[Vectorize-R2] Qdrant upsert failed for {}: {}",
|
||||
chunk_id, e
|
||||
);
|
||||
continue;
|
||||
}
|
||||
stored += 1;
|
||||
|
||||
Reference in New Issue
Block a user