diff --git a/apps/web/src/routes/dashboard.ts b/apps/web/src/routes/dashboard.ts index f79ce7a..4c73a9d 100644 --- a/apps/web/src/routes/dashboard.ts +++ b/apps/web/src/routes/dashboard.ts @@ -186,33 +186,29 @@ export const dashboard = new Elysia() if (!accountId) return redirect("/dashboard"); const monitors = await sql` - SELECT m.*, ( - SELECT row_to_json(p) FROM pings p - WHERE p.monitor_id = m.id ORDER BY p.checked_at DESC LIMIT 1 - ) as last_ping - FROM monitors m WHERE m.account_id = ${accountId} - ORDER BY m.created_at DESC + SELECT * FROM monitors WHERE account_id = ${accountId} ORDER BY created_at DESC `; - const monitorIds = monitors.map((m: any) => m.id); - let pingsMap: Record = {}; - if (monitorIds.length > 0) { - const allPings = await sql` - SELECT * FROM ( - SELECT p.*, ROW_NUMBER() OVER (PARTITION BY p.monitor_id, COALESCE(p.region,'__none__') ORDER BY p.checked_at DESC) as rn - FROM pings p WHERE p.monitor_id = ANY(${monitorIds}) - ) sub WHERE rn <= 20 ORDER BY monitor_id, checked_at ASC - `; - for (const p of allPings) { - if (!pingsMap[p.monitor_id]) pingsMap[p.monitor_id] = []; - pingsMap[p.monitor_id].push(p); - } - } + // One simple indexed query per monitor, run in parallel. Each is an index + // seek on (monitor_id, checked_at DESC) — microseconds. Trivially scalable + // and easy to reason about. + const pingResults = await Promise.all( + monitors.map((m: any) => sql` + SELECT * FROM pings + WHERE monitor_id = ${m.id} + ORDER BY checked_at DESC + LIMIT 20 + `) + ); - const monitorsWithPings = monitors.map((m: any) => ({ - ...m, - pings: pingsMap[m.id] || [], - })); + const monitorsWithPings = monitors.map((m: any, i: number) => { + const recent = pingResults[i] as any[]; // DESC order + return { + ...m, + last_ping: recent[0] ?? null, + pings: recent.slice().reverse(), // sparkline expects chronological ASC + }; + }); return html("home", { nav: "monitors", monitors: monitorsWithPings, accountId }); })