/** * GET /api/status/workers * Heartbeat snapshot for the three in-process workers: * • analyzer — analyzer_jobs * • rmm — rmm_executions * • sync — sync_schedules / sync_history (proxy for the scheduler) * * For each: last activity timestamp, in-flight count, last-1h success/ * failure totals. Cheap — just SELECT COUNT(*) FILTER queries. */ import { NextResponse } from 'next/server'; import { requireAuth } from '@/lib/auth-utils'; import postgresClient from '@/lib/services/postgres-client'; export interface WorkerSnapshot { name: string; lastActivity: string | null; inFlight: number; oneHour: { success: number; failure: number }; } export async function GET() { const { error } = await requireAuth(); if (error) return error; const [analyzerRes, rmmRes, syncRes] = await Promise.all([ postgresClient.query<{ last_activity: string | null; in_flight: string; ok_1h: string; fail_1h: string; }>( `SELECT GREATEST(MAX(queued_at), MAX(started_at), MAX(finished_at))::text AS last_activity, COUNT(*) FILTER (WHERE status IN ('queued','fetching','triaging','itglue','analyzing','deep_review'))::text AS in_flight, COUNT(*) FILTER (WHERE status = 'complete' AND finished_at >= NOW() - INTERVAL '1 hour')::text AS ok_1h, COUNT(*) FILTER (WHERE status = 'failed' AND finished_at >= NOW() - INTERVAL '1 hour')::text AS fail_1h FROM analyzer_jobs`, ), postgresClient.query<{ last_activity: string | null; in_flight: string; ok_1h: string; fail_1h: string; }>( `SELECT GREATEST(MAX(queued_at), MAX(started_at), MAX(completed_at))::text AS last_activity, COUNT(*) FILTER (WHERE status IN ('queued','running'))::text AS in_flight, COUNT(*) FILTER (WHERE status = 'complete' AND completed_at >= NOW() - INTERVAL '1 hour')::text AS ok_1h, COUNT(*) FILTER (WHERE status IN ('failed','timeout') AND completed_at >= NOW() - INTERVAL '1 hour')::text AS fail_1h FROM rmm_executions`, ), postgresClient.query<{ last_run: string | null; ok_1h: string; fail_1h: string; }>( `SELECT MAX(last_run)::text AS last_run, COUNT(*) FILTER (WHERE last_status = 'success' AND last_run >= NOW() - INTERVAL '1 hour')::text AS ok_1h, COUNT(*) FILTER (WHERE last_status = 'failed' AND last_run >= NOW() - INTERVAL '1 hour')::text AS fail_1h FROM sync_schedules WHERE is_enabled = true`, ), ]); const a = analyzerRes.rows[0]; const r = rmmRes.rows[0]; const s = syncRes.rows[0]; const workers: WorkerSnapshot[] = [ { name: 'Analyzer', lastActivity: a?.last_activity ?? null, inFlight: parseInt(a?.in_flight ?? '0', 10), oneHour: { success: parseInt(a?.ok_1h ?? '0', 10), failure: parseInt(a?.fail_1h ?? '0', 10), }, }, { name: 'RMM Overshell', lastActivity: r?.last_activity ?? null, inFlight: parseInt(r?.in_flight ?? '0', 10), oneHour: { success: parseInt(r?.ok_1h ?? '0', 10), failure: parseInt(r?.fail_1h ?? '0', 10), }, }, { name: 'Sync scheduler', lastActivity: s?.last_run ?? null, inFlight: 0, oneHour: { success: parseInt(s?.ok_1h ?? '0', 10), failure: parseInt(s?.fail_1h ?? '0', 10), }, }, ]; return NextResponse.json({ workers }); }