chore: backup before migration to new repo

This commit is contained in:
Warren
2026-04-23 16:46:02 +08:00
parent 13dd3b30f3
commit 59809dae1f
40 changed files with 5566 additions and 1783 deletions

View File

@@ -1,3 +1,3 @@
pub mod watcher;
pub use watcher::{watch_directories, WatcherConfig};
pub use watcher::{run_watcher, WatcherConfig};

View File

@@ -1,8 +1,11 @@
use anyhow::Result;
use notify::{Config, Event, EventKind, RecommendedWatcher, RecursiveMode, Watcher};
use std::path::Path;
use std::sync::Arc;
use tokio::sync::mpsc;
use tokio::time;
use tracing::{error, info, warn};
use crate::core::db::{Database, PostgresDb};
use crate::core::ingestion::IngestionService;
pub struct WatcherConfig {
pub directories: Vec<String>,
@@ -11,31 +14,94 @@ pub struct WatcherConfig {
impl Default for WatcherConfig {
fn default() -> Self {
// Default to SFTP demo directory if not specified
let default_dir = std::env::var("MOMENTRY_SFTP_ROOT")
.unwrap_or_else(|_| "/Users/accusys/momentry/var/sftpgo/data/demo/".to_string());
Self {
directories: vec![],
poll_interval_ms: 5000,
directories: vec![default_dir],
poll_interval_ms: 60000, // 60 seconds polling interval
}
}
}
pub async fn watch_directories(config: WatcherConfig, tx: mpsc::Sender<String>) -> Result<()> {
// TODO: Implement directory watcher
//
// Options:
// 1. Use notify crate for file system events
// 2. Use polling as fallback
//
// When new video file is detected:
// - Send job to Redis queue
// - Trigger registration process
/// Starts the file watcher in the background.
/// Scans directories for video files and registers them if not already present.
pub async fn run_watcher() -> Result<()> {
let config = WatcherConfig::default();
let dirs = config.directories.clone();
println!("Watching directories: {:?}", config.directories);
for dir in &config.directories {
if Path::new(dir).exists() {
println!("Directory exists: {}", dir);
}
if dirs.is_empty() {
warn!("No directories configured for watching.");
return Err(anyhow::anyhow!("No watch directories"));
}
info!("Initializing Database for Watcher...");
// Use Database::init() which handles config and pool creation
let db = PostgresDb::init().await?;
let service = Arc::new(IngestionService::new(db));
info!("Starting Ingestion Poller for: {:?}", dirs);
// Spawn background task
tokio::spawn(async move {
let mut interval = time::interval(time::Duration::from_millis(config.poll_interval_ms));
// Run once immediately on startup to catch existing files
scan_and_ingest(&dirs, &service).await;
loop {
interval.tick().await;
scan_and_ingest(&dirs, &service).await;
}
});
Ok(())
}
async fn scan_and_ingest(directories: &[String], service: &Arc<IngestionService>) {
// Allowed extensions list
let allowed_extensions = vec!["mp4", "mov", "mkv"];
info!("Scanning directories for new videos...");
for dir in directories {
let path = Path::new(dir);
if !path.exists() {
warn!("Directory does not exist, skipping: {}", dir);
continue;
}
if let Ok(entries) = std::fs::read_dir(path) {
for entry in entries.flatten() {
let file_path = entry.path();
if file_path.is_file() {
// Check extension
let is_video = if let Some(ext) = file_path.extension().and_then(|e| e.to_str())
{
allowed_extensions.contains(&ext.to_lowercase().as_str())
} else {
false
};
if is_video {
if let Some(p_str) = file_path.to_str() {
// Try to ingest. The service checks if it already exists.
match service.ingest(p_str).await {
Ok(Some(uuid)) => {
info!("Auto-registered: {} -> {}", file_path.display(), uuid);
}
Ok(None) => {
// Already registered
}
Err(e) => {
error!("Failed to ingest {}: {}", file_path.display(), e);
}
}
}
}
}
}
}
}
}