fix: run_id = hash(monitor_id, interval_bucket) — unique per window, consistent across regions

This commit is contained in:
M1 2026-03-18 17:03:17 +04:00
parent b6a66ddb21
commit 7b98ae78e5
2 changed files with 10 additions and 4 deletions

View File

@ -53,14 +53,20 @@ pub async fn fetch_and_run(
let coordinator_url = coordinator_url.to_string(); let coordinator_url = coordinator_url.to_string();
let token = token.to_string(); let token = token.to_string();
let region_owned = region.to_string(); let region_owned = region.to_string();
// Derive run_id from the monitor's scheduled_at bucket // Derive run_id by hashing (monitor_id, interval_bucket) so every region
// checking within the same scheduled window gets the same short ID.
let run_id_owned = { let run_id_owned = {
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
let epoch = monitor.scheduled_at.as_deref() let epoch = monitor.scheduled_at.as_deref()
.and_then(|s| chrono::DateTime::parse_from_rfc3339(s).ok()) .and_then(|s| chrono::DateTime::parse_from_rfc3339(s).ok())
.map(|dt| dt.timestamp()) .map(|dt| dt.timestamp())
.unwrap_or_else(|| chrono::Utc::now().timestamp()); .unwrap_or_else(|| chrono::Utc::now().timestamp());
let bucket = epoch / monitor.interval_s; let bucket = epoch / monitor.interval_s;
format!("{}:{}", &monitor.id[..8.min(monitor.id.len())], bucket) let mut h = DefaultHasher::new();
monitor.id.hash(&mut h);
bucket.hash(&mut h);
format!("{:016x}", h.finish())
}; };
let in_flight = in_flight.clone(); let in_flight = in_flight.clone();
tokio::spawn(async move { tokio::spawn(async move {

View File

@ -107,7 +107,7 @@
<td class="px-4 py-2 text-gray-300"><%= c.status_code != null ? c.status_code : '—' %></td> <td class="px-4 py-2 text-gray-300"><%= c.status_code != null ? c.status_code : '—' %></td>
<td class="px-4 py-2 text-gray-300"><%= c.latency_ms != null ? c.latency_ms + 'ms' : '—' %></td> <td class="px-4 py-2 text-gray-300"><%= c.latency_ms != null ? c.latency_ms + 'ms' : '—' %></td>
<td class="px-4 py-2 text-gray-500 text-sm" title="<%= c.region || '' %>"><%= c.region ? (regionFlag[c.region] || '🌐') + ' ' + c.region : '—' %></td> <td class="px-4 py-2 text-gray-500 text-sm" title="<%= c.region || '' %>"><%= c.region ? (regionFlag[c.region] || '🌐') + ' ' + c.region : '—' %></td>
<td class="px-4 py-2 text-gray-600 font-mono text-xs" title="<%= c.run_id || '' %>"><%= c.run_id ? c.run_id.slice(0, 8) : '—' %></td> <td class="px-4 py-2 text-gray-600 font-mono text-xs" title="<%= c.run_id || '' %>"><%= c.run_id ? c.run_id.slice(0, 8) + '…' : '—' %></td>
<td class="px-4 py-2 text-gray-500"><%~ it.timeAgoSSR(c.checked_at) %><% if (c.jitter_ms != null) { %> <span class="text-gray-600 text-xs">(+<%= c.jitter_ms %>ms)</span><% } %></td> <td class="px-4 py-2 text-gray-500"><%~ it.timeAgoSSR(c.checked_at) %><% if (c.jitter_ms != null) { %> <span class="text-gray-600 text-xs">(+<%= c.jitter_ms %>ms)</span><% } %></td>
<td class="px-4 py-2 text-red-400/70 text-xs truncate max-w-[200px]"><%= c.error ? c.error : '' %></td> <td class="px-4 py-2 text-red-400/70 text-xs truncate max-w-[200px]"><%= c.error ? c.error : '' %></td>
</tr> </tr>
@ -344,7 +344,7 @@
<td class="px-4 py-2 text-gray-300">${ping.status_code ?? '—'}</td> <td class="px-4 py-2 text-gray-300">${ping.status_code ?? '—'}</td>
<td class="px-4 py-2 text-gray-300">${ping.latency_ms != null ? ping.latency_ms + 'ms' : '—'}</td> <td class="px-4 py-2 text-gray-300">${ping.latency_ms != null ? ping.latency_ms + 'ms' : '—'}</td>
<td class="px-4 py-2 text-gray-500 text-sm" title="${ping.region || ''}">${regionDisplay}</td> <td class="px-4 py-2 text-gray-500 text-sm" title="${ping.region || ''}">${regionDisplay}</td>
<td class="px-4 py-2 text-gray-600 font-mono text-xs" title="${ping.run_id || ''}">${ping.run_id ? ping.run_id.slice(0, 8) : '—'}</td> <td class="px-4 py-2 text-gray-600 font-mono text-xs" title="${ping.run_id || ''}">${ping.run_id ? ping.run_id.slice(0, 8) + '…' : '—'}</td>
<td class="px-4 py-2 text-gray-500">${timeAgo(ping.checked_at)}${ping.jitter_ms != null ? ` <span class="text-gray-600 text-xs">(+${ping.jitter_ms}ms)</span>` : ''}</td> <td class="px-4 py-2 text-gray-500">${timeAgo(ping.checked_at)}${ping.jitter_ms != null ? ` <span class="text-gray-600 text-xs">(+${ping.jitter_ms}ms)</span>` : ''}</td>
<td class="px-4 py-2 text-red-400/70 text-xs truncate max-w-[200px]">${ping.error ? escapeHtml(ping.error) : ''}</td> <td class="px-4 py-2 text-red-400/70 text-xs truncate max-w-[200px]">${ping.error ? escapeHtml(ping.error) : ''}</td>
`; `;