diff --git a/contracts/predict-iq/src/modules/monitoring.rs b/contracts/predict-iq/src/modules/monitoring.rs index f1604a6..aaa7e46 100644 --- a/contracts/predict-iq/src/modules/monitoring.rs +++ b/contracts/predict-iq/src/modules/monitoring.rs @@ -18,6 +18,9 @@ pub fn track_error(e: &Env) { .unwrap_or(0); count += 1; e.storage().persistent().set(&DataKey::ErrorCount, &count); + e.storage() + .persistent() + .set(&DataKey::LastObservation, &e.ledger().timestamp()); if count > 10 { e.storage().persistent().set( @@ -32,8 +35,80 @@ pub fn track_error(e: &Env) { /// Issue #44: Emit MonitorReset event so devops can track resets on-chain. pub fn reset_monitoring(e: &Env) { + let previous_error_count: u32 = e + .storage() + .persistent() + .get(&DataKey::ErrorCount) + .unwrap_or(0); + let previous_last_observation: u64 = e + .storage() + .persistent() + .get(&DataKey::LastObservation) + .unwrap_or(0); + e.storage().persistent().set(&DataKey::ErrorCount, &0u32); + e.storage().persistent().set(&DataKey::LastObservation, &0u64); + + let resetter = crate::modules::admin::get_admin(e).unwrap_or(e.current_contract_address()); + crate::modules::events::emit_monitoring_state_reset( + e, + resetter, + previous_error_count, + previous_last_observation, + ); +} + +#[cfg(test)] +mod tests { + use super::{reset_monitoring, track_error, DataKey}; + use soroban_sdk::{testutils::{Events, Ledger}, Env}; - e.events() - .publish((symbol_short!("mon_reset"),), 0u32); + #[test] + fn reset_monitoring_clears_error_trackers() { + let e = Env::default(); + e.ledger().set_timestamp(777); + + track_error(&e); + track_error(&e); + + let before_count: u32 = e.storage().persistent().get(&DataKey::ErrorCount).unwrap_or(0); + let before_obs: u64 = e + .storage() + .persistent() + .get(&DataKey::LastObservation) + .unwrap_or(0); + assert_eq!(before_count, 2); + assert_eq!(before_obs, 777); + + reset_monitoring(&e); + + let after_count: u32 = e.storage().persistent().get(&DataKey::ErrorCount).unwrap_or(1); + let after_obs: u64 = e + .storage() + .persistent() + .get(&DataKey::LastObservation) + .unwrap_or(1); + + assert_eq!(after_count, 0); + assert_eq!(after_obs, 0); + } + + #[test] + fn reset_monitoring_emits_event_with_previous_values() { + let e = Env::default(); + e.ledger().set_timestamp(1234); + + track_error(&e); + track_error(&e); + + reset_monitoring(&e); + + let events = e.events().all(); + assert!(!events.is_empty()); + + let events_debug = format!("{:?}", events); + assert!(events_debug.contains("mon_reset")); + assert!(events_debug.contains("2")); + assert!(events_debug.contains("1234")); + } }