//! 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 ); } } }