feat: lookahead scheduling — API returns scheduled_at_ms, nodes sleep-until for tight coordination
This commit is contained in:
@@ -31,18 +31,22 @@ export const internal = new Elysia({ prefix: "/internal", detail: { hide: true }
|
||||
return {};
|
||||
})
|
||||
|
||||
// Returns monitors that are due for a check.
|
||||
// When a region is provided, due-ness and scheduled_at are based on
|
||||
// the last ping from that specific region — so each region has its own
|
||||
// independent schedule and they don't drift against each other.
|
||||
// Returns monitors due within the next `lookahead_ms` milliseconds (default 2000).
|
||||
// Nodes receive scheduled_at as an exact unix ms timestamp and sleep until that
|
||||
// moment before firing — all regions coordinate to the same scheduled slot.
|
||||
.get("/due", async ({ request }) => {
|
||||
const region = new URL(request.url).searchParams.get('region') || undefined;
|
||||
const params = new URL(request.url).searchParams;
|
||||
const region = params.get('region') || undefined;
|
||||
const lookaheadMs = Math.min(Number(params.get('lookahead_ms') || 2000), 10000);
|
||||
|
||||
const monitors = await sql`
|
||||
SELECT m.id, m.url, m.method, m.request_headers, m.request_body, m.timeout_ms, m.interval_s, m.query, m.regions,
|
||||
CASE
|
||||
WHEN last.checked_at IS NULL THEN now()
|
||||
ELSE last.checked_at + (m.interval_s || ' seconds')::interval
|
||||
END AS scheduled_at
|
||||
EXTRACT(EPOCH FROM (
|
||||
CASE
|
||||
WHEN last.checked_at IS NULL THEN now()
|
||||
ELSE last.checked_at + (m.interval_s || ' seconds')::interval
|
||||
END
|
||||
))::bigint * 1000 AS scheduled_at_ms
|
||||
FROM monitors m
|
||||
LEFT JOIN LATERAL (
|
||||
SELECT checked_at FROM pings
|
||||
@@ -52,7 +56,7 @@ export const internal = new Elysia({ prefix: "/internal", detail: { hide: true }
|
||||
) last ON true
|
||||
WHERE m.enabled = true
|
||||
AND (last.checked_at IS NULL
|
||||
OR last.checked_at < now() - (m.interval_s || ' seconds')::interval)
|
||||
OR last.checked_at < now() - (m.interval_s || ' seconds')::interval + (${lookaheadMs} || ' milliseconds')::interval)
|
||||
AND (
|
||||
array_length(m.regions, 1) IS NULL
|
||||
OR m.regions = '{}'
|
||||
|
||||
Reference in New Issue
Block a user