diff --git a/k-tv-backend/api/src/library_scheduler.rs b/k-tv-backend/api/src/library_scheduler.rs new file mode 100644 index 0000000..7125b8a --- /dev/null +++ b/k-tv-backend/api/src/library_scheduler.rs @@ -0,0 +1,64 @@ +//! Background library sync task. +//! Fires 10 seconds after startup, then every N hours (read from app_settings). + +use std::sync::Arc; +use std::time::Duration; + +use domain::IProviderRegistry; + +const STARTUP_DELAY_SECS: u64 = 10; +const DEFAULT_INTERVAL_HOURS: u64 = 6; + +pub async fn run_library_sync( + sync_adapter: Arc, + registry: Arc>>, + app_settings_repo: Arc, +) { + tokio::time::sleep(Duration::from_secs(STARTUP_DELAY_SECS)).await; + + loop { + tick(&sync_adapter, ®istry).await; + + let interval_hours = load_interval_hours(&app_settings_repo).await; + tokio::time::sleep(Duration::from_secs(interval_hours * 3600)).await; + } +} + +async fn load_interval_hours(repo: &Arc) -> u64 { + repo.get("library_sync_interval_hours") + .await + .ok() + .flatten() + .and_then(|v| v.parse::().ok()) + .unwrap_or(DEFAULT_INTERVAL_HOURS) +} + +async fn tick( + sync_adapter: &Arc, + registry: &Arc>>, +) { + let reg = registry.read().await; + let provider_ids: Vec = reg.provider_ids(); + drop(reg); + + for provider_id in provider_ids { + let reg = registry.read().await; + let provider = match reg.get_provider(&provider_id) { + Some(p) => p, + None => continue, + }; + drop(reg); + + tracing::info!("library-sync: syncing provider '{}'", provider_id); + let result = sync_adapter.sync_provider(provider.as_ref(), &provider_id).await; + + if let Some(ref err) = result.error { + tracing::warn!("library-sync: provider '{}' failed: {}", provider_id, err); + } else { + tracing::info!( + "library-sync: provider '{}' done — {} items in {}ms", + provider_id, result.items_found, result.duration_ms + ); + } + } +}