From b6a66ddb21bddc91ceebc1c2289ee90223f2718f Mon Sep 17 00:00:00 2001 From: M1 Date: Wed, 18 Mar 2026 16:46:30 +0400 Subject: [PATCH] fix: run_id derived from scheduled_at bucket so all regions share same ID per window --- apps/monitor/Cargo.toml | 2 +- apps/monitor/src/runner.rs | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/apps/monitor/Cargo.toml b/apps/monitor/Cargo.toml index 7fcc5cd..f40935c 100644 --- a/apps/monitor/Cargo.toml +++ b/apps/monitor/Cargo.toml @@ -20,4 +20,4 @@ webpki-roots = "0.26" x509-parser = "0.16" tokio-rustls = "0.26" chrono = { version = "0.4", features = ["serde"] } -uuid = { version = "1", features = ["v4"] } + diff --git a/apps/monitor/src/runner.rs b/apps/monitor/src/runner.rs index 37a919a..8cdd72e 100644 --- a/apps/monitor/src/runner.rs +++ b/apps/monitor/src/runner.rs @@ -33,8 +33,9 @@ pub async fn fetch_and_run( let n = monitors.len(); if n == 0 { return Ok(0); } - // One run_id per fetch batch — groups all checks from this cycle across regions - let run_id = uuid::Uuid::new_v4().to_string(); + // run_id is computed deterministically per monitor+interval bucket so all regions + // checking within the same scheduled window share the same ID. + // Format: first 8 chars of monitor_id + ':' + floor(scheduled_at_epoch / interval_s) // Spawn all checks — fire and forget, skip if already in-flight let mut spawned = 0usize; @@ -52,7 +53,15 @@ pub async fn fetch_and_run( let coordinator_url = coordinator_url.to_string(); let token = token.to_string(); let region_owned = region.to_string(); - let run_id_owned = run_id.clone(); + // Derive run_id from the monitor's scheduled_at bucket + let run_id_owned = { + let epoch = monitor.scheduled_at.as_deref() + .and_then(|s| chrono::DateTime::parse_from_rfc3339(s).ok()) + .map(|dt| dt.timestamp()) + .unwrap_or_else(|| chrono::Utc::now().timestamp()); + let bucket = epoch / monitor.interval_s; + format!("{}:{}", &monitor.id[..8.min(monitor.id.len())], bucket) + }; let in_flight = in_flight.clone(); tokio::spawn(async move { let timeout_ms = monitor.timeout_ms.unwrap_or(30000);