use tokio::task::JoinHandle; use tracing::info; use pom::alerts::Alerter; use pom::checks::whois; use pom::config::Config; use pom::db; pub(crate) fn spawn_whois_tasks( config: &Config, pool: &sqlx::SqlitePool, cancel: &tokio_util::sync::CancellationToken, alerter: &Option, ) -> Vec> { let whois_interval_secs = config.serve.tls_check_interval_secs; let mut handles = Vec::new(); for name in config.target_names() { let target_config = config.get_target(&name).unwrap().clone(); let Some(whois_config) = target_config.whois else { continue }; let label = target_config.label.clone(); let pool = pool.clone(); let alerter = alerter.clone(); let cancel = cancel.clone(); let warn_days = whois_config.warn_days; info!("{name}: WHOIS check every {whois_interval_secs}s (domain={})", whois_config.domain); handles.push(tokio::spawn(async move { let mut interval = tokio::time::interval( std::time::Duration::from_secs(whois_interval_secs), ); interval.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Delay); interval.tick().await; // consume immediate first tick loop { tokio::select! { _ = cancel.cancelled() => break, _ = interval.tick() => {} } let result = whois::check_whois(&name, &whois_config).await; info!("{}: WHOIS {} — {:?} days remaining", name, whois_config.domain, result.days_remaining); if let Err(e) = db::insert_whois_check(&pool, &result).await { tracing::error!("{name}: failed to store WHOIS check: {e}"); } if let Some(ref alerter) = alerter { if let Some(ref error) = result.error { alerter.send_whois_error_alert(&name, &label, &whois_config.domain, error).await; } else if let Some(days) = result.days_remaining && days <= warn_days as i64 { alerter.send_whois_expiry_alert(&name, &label, &whois_config.domain, days).await; } } } })); } handles }