use crate::{mail::send_mail, Config, STATUS}; use chrono::{DateTime, Utc}; use std::{ collections::{BTreeMap, VecDeque}, sync::Arc, }; use tokio::sync::RwLock; static LAST_STATUS: RwLock> = RwLock::const_new(BTreeMap::new()); pub static LOG: RwLock> = RwLock::const_new(VecDeque::new()); pub struct Event { pub time: DateTime, pub service: usize, pub check: usize, pub error: Option, } pub async fn update_service( config: Arc, service: usize, check: usize, error: Option<(String, String)>, ) -> anyhow::Result<()> { let mut last_status = LAST_STATUS.write().await; let last_status = last_status.entry(service).or_insert(true); eprintln!("{service} {error:?}"); let current_status = { let status = STATUS.read().await; !status .range((service, usize::MIN)..(service, usize::MAX)) .any(|(_, v)| v.is_err()) }; if *last_status != current_status { *last_status = current_status; let mut log = LOG.write().await; log.push_front(Event { error: error.clone().map(|(e, _)| e), service, check, time: Utc::now(), }); while log.len() > 32 { log.pop_back(); } if let Some((_short, long)) = error.clone() { send_mail(&config, service, check, long).await?; } } Ok(()) }