import { NextRequest } from 'next/server'; import { setRunnerHeartbeat, getRunnerHeartbeat, RUNNER_TIMEOUT_MS, RUNNER_EXPECTED_VERSION } from '@/lib/db'; import { corsJson, corsPreflight } from '../cors'; /** The runner checks in. Timestamped server-side so a runner with a skewed clock * doesn't read as permanently offline (or permanently online). */ export async function POST(req: NextRequest) { try { const body = await req.json().catch(() => ({})) as Record; setRunnerHeartbeat({ host: typeof body.host === 'string' ? body.host : undefined, pid: typeof body.pid === 'number' ? body.pid : undefined, dryRun: body.dryRun === true, version: typeof body.version === 'string' ? body.version : undefined, busy: body.busy === true, }); return corsJson({ ok: true }); } catch (err: any) { return corsJson({ error: err?.message ?? 'Failed to record heartbeat' }, { status: 500 }); } } export async function GET() { const hb = getRunnerHeartbeat(); if (!hb) return corsJson({ online: false, lastSeen: null, ageMs: null }); const ageMs = Date.now() - hb.at; return corsJson({ online: ageMs < RUNNER_TIMEOUT_MS, lastSeen: hb.at, ageMs, host: hb.host ?? null, pid: hb.pid ?? null, dryRun: !!hb.dryRun, busy: !!hb.busy, version: hb.version ?? null, expectedVersion: RUNNER_EXPECTED_VERSION, stale: (hb.version ?? '') !== RUNNER_EXPECTED_VERSION, }); } export async function OPTIONS() { return corsPreflight(); }