feat: independent TKG processing mechanism with operation logging

- Created src/core/tkg/ module with service, log, and models
- Added tkg_operation_log table for tracking all TKG operations
- TkgService: build, rebuild (with force option), delete, get_operations
- Updated rebuild endpoint with force parameter
- Added GET /api/v1/file/:file_uuid/tkg for operation history
- Added DELETE /api/v1/file/:file_uuid/tkg for TKG deletion
- TKG rebuild now always triggers Rule 2 (even with 0 edges)
- Full audit trail for all TKG operations (create/update/delete/rebuild)
This commit is contained in:
Accusys
2026-07-07 03:15:59 +08:00
parent f56bdb7fbb
commit bb606f52f5
7 changed files with 429 additions and 38 deletions
+94
View File
@@ -0,0 +1,94 @@
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TkgOperationLog {
pub id: i64,
pub file_uuid: String,
pub operation: String,
pub node_type: Option<String>,
pub edge_type: Option<String>,
pub nodes_created: i32,
pub nodes_updated: i32,
pub nodes_deleted: i32,
pub edges_created: i32,
pub edges_updated: i32,
pub edges_deleted: i32,
pub status: String,
pub error_message: Option<String>,
pub started_at: String,
pub completed_at: Option<String>,
pub properties: Option<serde_json::Value>,
}
#[derive(Debug, Clone, Default)]
pub struct TkgNodeStats {
pub created: i32,
pub updated: i32,
pub deleted: i32,
}
#[derive(Debug, Clone, Default)]
pub struct TkgEdgeStats {
pub created: i32,
pub updated: i32,
pub deleted: i32,
}
#[derive(Debug, Clone, Default)]
pub struct TkgBuildStats {
pub face_track_nodes: i32,
pub gaze_track_nodes: i32,
pub lip_track_nodes: i32,
pub text_region_nodes: i32,
pub appearance_trace_nodes: i32,
pub accessory_nodes: i32,
pub object_nodes: i32,
pub hand_nodes: i32,
pub speaker_nodes: i32,
pub co_occurrence_edges: i32,
pub speaker_face_edges: i32,
pub face_face_edges: i32,
pub mutual_gaze_edges: i32,
pub lip_sync_edges: i32,
pub has_appearance_edges: i32,
pub wears_edges: i32,
pub hand_object_edges: i32,
}
impl TkgBuildStats {
pub fn total_nodes(&self) -> i32 {
self.face_track_nodes + self.gaze_track_nodes + self.lip_track_nodes
+ self.text_region_nodes + self.appearance_trace_nodes + self.accessory_nodes
+ self.object_nodes + self.hand_nodes + self.speaker_nodes
}
pub fn total_edges(&self) -> i32 {
self.co_occurrence_edges + self.speaker_face_edges + self.face_face_edges
+ self.mutual_gaze_edges + self.lip_sync_edges + self.has_appearance_edges
+ self.wears_edges + self.hand_object_edges
}
pub fn to_json(&self) -> serde_json::Value {
serde_json::json!({
"face_track_nodes": self.face_track_nodes,
"gaze_track_nodes": self.gaze_track_nodes,
"lip_track_nodes": self.lip_track_nodes,
"text_region_nodes": self.text_region_nodes,
"appearance_trace_nodes": self.appearance_trace_nodes,
"accessory_nodes": self.accessory_nodes,
"object_nodes": self.object_nodes,
"hand_nodes": self.hand_nodes,
"speaker_nodes": self.speaker_nodes,
"co_occurrence_edges": self.co_occurrence_edges,
"speaker_face_edges": self.speaker_face_edges,
"face_face_edges": self.face_face_edges,
"mutual_gaze_edges": self.mutual_gaze_edges,
"lip_sync_edges": self.lip_sync_edges,
"has_appearance_edges": self.has_appearance_edges,
"wears_edges": self.wears_edges,
"hand_object_edges": self.hand_object_edges,
"total_nodes": self.total_nodes(),
"total_edges": self.total_edges(),
})
}
}