feat: trace-level matching, health watcher/worker status, timezone config

This commit is contained in:
Accusys
2026-05-21 01:08:30 +08:00
parent 8ede4be159
commit bebaa743ed
60 changed files with 6110 additions and 1586 deletions

View File

@@ -37,7 +37,8 @@ pub async fn run_watcher() -> Result<()> {
info!("Watch directories: {:?}", dirs);
tokio::spawn(async move {
let mut interval = time::interval(std::time::Duration::from_millis(config.poll_interval_ms));
let mut interval =
time::interval(std::time::Duration::from_millis(config.poll_interval_ms));
let mut known = std::collections::HashSet::new();
loop {
interval.tick().await;
@@ -109,15 +110,43 @@ async fn auto_register_file(file_path: &str) {
}
};
let file_name = pre.get("file_name").and_then(|v| v.as_str()).unwrap_or("unknown").to_string();
let file_name = pre
.get("file_name")
.and_then(|v| v.as_str())
.unwrap_or("unknown")
.to_string();
let probe = pre.get("probe_json").cloned().unwrap_or_default();
let file_type = pre.get("file_type").and_then(|v| v.as_str()).unwrap_or("unknown").to_string();
let canonical_path = pre.get("file_path").and_then(|v| v.as_str()).unwrap_or(file_path).to_string();
let file_type = pre
.get("file_type")
.and_then(|v| v.as_str())
.unwrap_or("unknown")
.to_string();
let canonical_path = pre
.get("file_path")
.and_then(|v| v.as_str())
.unwrap_or(file_path)
.to_string();
let duration = probe.get("format").and_then(|f| f.get("duration")).and_then(|v| v.as_f64()).unwrap_or(0.0);
let width = probe.get("format").and_then(|f| f.get("width")).and_then(|v| v.as_u64()).unwrap_or(0) as u32;
let height = probe.get("format").and_then(|f| f.get("height")).and_then(|v| v.as_u64()).unwrap_or(0) as u32;
let fps_val = probe.get("format").and_then(|f| f.get("fps")).and_then(|v| v.as_f64()).unwrap_or(0.0);
let duration = probe
.get("format")
.and_then(|f| f.get("duration"))
.and_then(|v| v.as_f64())
.unwrap_or(0.0);
let width = probe
.get("format")
.and_then(|f| f.get("width"))
.and_then(|v| v.as_u64())
.unwrap_or(0) as u32;
let height = probe
.get("format")
.and_then(|f| f.get("height"))
.and_then(|v| v.as_u64())
.unwrap_or(0) as u32;
let fps_val = probe
.get("format")
.and_then(|f| f.get("fps"))
.and_then(|v| v.as_f64())
.unwrap_or(0.0);
let record = VideoRecord {
id: 0,
@@ -158,7 +187,10 @@ async fn auto_register_file(file_path: &str) {
match db.register_video(&record).await {
Ok(id) => info!("[WATCHER] Auto-registered {} (id={})", record.file_uuid, id),
Err(e) => warn!("[WATCHER] Auto-register failed for {}: {}", record.file_uuid, e),
Err(e) => warn!(
"[WATCHER] Auto-register failed for {}: {}",
record.file_uuid, e
),
}
}
@@ -175,10 +207,14 @@ pub async fn pre_process_file(file_path: &str) -> Option<String> {
let output_dir = std::env::var("MOMENTRY_OUTPUT_DIR")
.unwrap_or_else(|_| "/Users/accusys/momentry/output_dev".to_string());
let birthday = std::fs::metadata(&path).ok()
let birthday = std::fs::metadata(&path)
.ok()
.and_then(|m| m.modified().ok())
.map(|t| {
let secs = t.duration_since(std::time::UNIX_EPOCH).unwrap_or_default().as_secs();
let secs = t
.duration_since(std::time::UNIX_EPOCH)
.unwrap_or_default()
.as_secs();
chrono::DateTime::from_timestamp(secs as i64, 0)
.map(|dt| dt.to_rfc3339())
.unwrap_or_else(|| chrono::Utc::now().to_rfc3339())
@@ -186,9 +222,8 @@ pub async fn pre_process_file(file_path: &str) -> Option<String> {
.unwrap_or_else(|| chrono::Utc::now().to_rfc3339());
let mac = crate::core::storage::uuid::get_mac_address();
let file_uuid = crate::core::storage::uuid::compute_birth_uuid(
&mac, &birthday, &canonical_str, &filename,
);
let file_uuid =
crate::core::storage::uuid::compute_birth_uuid(&mac, &birthday, &canonical_str, &filename);
let pre_path = std::path::PathBuf::from(&output_dir).join(format!("{}.pre.json", file_uuid));
if pre_path.exists() {
@@ -198,15 +233,22 @@ pub async fn pre_process_file(file_path: &str) -> Option<String> {
info!("[PRE-PROCESS] Pre-processing: {} → {}", filename, file_uuid);
let content_hash = crate::core::storage::content_hash::compute_sha256(&path).unwrap_or_default();
let content_hash =
crate::core::storage::content_hash::compute_sha256(&path).unwrap_or_default();
let scripts_dir = std::env::var("MOMENTRY_SCRIPTS_DIR")
.unwrap_or_else(|_| "/Users/accusys/momentry_core_0.1/scripts".to_string());
let python_path = std::env::var("MOMENTRY_PYTHON_PATH")
.unwrap_or_else(|_| "/opt/homebrew/bin/python3.11".to_string());
let probe_json = crate::core::probe::unified::unified_probe(&path, &scripts_dir, &python_path).await;
let probe_json =
crate::core::probe::unified::unified_probe(&path, &scripts_dir, &python_path).await;
let file_type = probe_json.get("format").and_then(|f| f.get("file_type")).and_then(|v| v.as_str()).unwrap_or("unknown").to_string();
let file_type = probe_json
.get("format")
.and_then(|f| f.get("file_type"))
.and_then(|v| v.as_str())
.unwrap_or("unknown")
.to_string();
let pre_data = serde_json::json!({
"file_name": filename,