← back to Trademarks Copyright
src/app/api/health/route.ts
44 lines
import { NextResponse } from "next/server";
import { query } from "@/lib/db";
import { qwenIsUp, QWEN_MODEL_NAME } from "@/lib/qwen";
import { currentBackend } from "@/lib/email";
export const runtime = "nodejs";
export const dynamic = "force-dynamic";
export async function GET() {
const start = Date.now();
const checks: Record<string, { ok: boolean; detail?: string; latencyMs?: number }> = {};
try {
const t0 = Date.now();
const { rows } = await query<{ n: string }>("SELECT COUNT(*)::text AS n FROM items");
checks.db = { ok: true, detail: `${rows[0].n} items`, latencyMs: Date.now() - t0 };
} catch (e) {
checks.db = { ok: false, detail: (e as Error).message };
}
try {
const t0 = Date.now();
const up = await qwenIsUp();
checks.ollama = { ok: up, detail: up ? QWEN_MODEL_NAME : "not reachable", latencyMs: Date.now() - t0 };
} catch (e) {
checks.ollama = { ok: false, detail: (e as Error).message };
}
checks.email_backend = { ok: true, detail: currentBackend() };
checks.stripe = { ok: true, detail: process.env.STRIPE_SECRET_KEY ? "configured" : "dev-mock" };
const overall = Object.values(checks).every((c) => c.ok);
return NextResponse.json(
{
ok: overall,
timestamp: new Date().toISOString(),
uptime_s: Math.floor(process.uptime()),
latency_ms: Date.now() - start,
checks,
},
{ status: overall ? 200 : 503 }
);
}