import type { DashboardResponse, RuntimeMode } from "../../shared/api"; import type { ProbeStore } from "../checker/store"; import { formatDuration, jsonResponse, mapCheckResult } from "../helpers"; import { analyzeIncidentSequence, calculateCurrentStreak, type MetricCheckpoint } from "../metrics"; import { validateDashboardWindow, validateRecentLimit } from "../middleware"; export function handleDashboard(url: URL, store: ProbeStore, mode: RuntimeMode): Response { const windowResult = validateDashboardWindow(url.searchParams.get("window"), mode); if (windowResult instanceof Response) return windowResult; const limitResult = validateRecentLimit(url.searchParams.get("recentLimit"), mode); if (limitResult instanceof Response) return limitResult; const targets = store.getTargets(); const latestChecksMap = store.getLatestChecksMap(); const windowStats = store.getAllTargetWindowStats(windowResult.from, windowResult.to); const recentSamplesMap = store.getAllRecentSamples(limitResult.recentLimit); const incidentStates = groupDashboardIncidentStates( store.getDashboardIncidentStates(windowResult.from, windowResult.to), ); let up = 0; let down = 0; let lastCheckTime: null | string = null; let incidents = 0; const responseTargets: DashboardResponse["targets"] = targets.map((target) => { const latest = latestChecksMap.get(target.id) ?? null; const stats = windowStats.get(target.id) ?? { availability: 0, downChecks: 0, totalChecks: 0, upChecks: 0 }; const recentSamples = recentSamplesMap.get(target.id) ?? []; const currentStreak = calculateCurrentStreak( recentSamples.map((sample) => ({ durationMs: sample.duration_ms, matched: sample.matched === 1, timestamp: sample.timestamp, })), limitResult.recentLimit, ); if (latest?.matched === 1) { up++; } else { down++; } if (latest && (!lastCheckTime || latest.timestamp > lastCheckTime)) { lastCheckTime = latest.timestamp; } incidents += analyzeIncidentSequence( incidentStates.get(target.id) ?? [], windowResult.from, windowResult.to, ).incidentCount; return { currentStreak, group: target.grp, id: target.id, interval: formatDuration(target.interval_ms), latestCheck: latest ? mapCheckResult(latest) : null, name: target.name, recentSamples: recentSamples.map((sample) => ({ durationMs: sample.duration_ms, timestamp: sample.timestamp, up: sample.matched === 1, })), stats, target: target.target, type: target.type, }; }); const response: DashboardResponse = { summary: { down, incidents, lastCheckTime, total: targets.length, up, window: windowResult, }, targets: responseTargets, }; return jsonResponse(response, { mode }); } function groupDashboardIncidentStates( states: Array<{ matched: number; target_id: number; timestamp: string }>, ): Map { const result = new Map(); for (const state of states) { const list = result.get(state.target_id) ?? []; list.push({ durationMs: null, matched: state.matched === 1, timestamp: state.timestamp }); result.set(state.target_id, list); } return result; }