import { NextResponse } from "next/server"; import { prisma } from "@capakraken/db"; import { createConnection } from "net"; export const dynamic = "force-dynamic"; export const runtime = "nodejs"; const REDIS_URL = process.env["REDIS_URL"] ?? "redis://localhost:6380"; async function checkPostgres(): Promise<"ok" | "error"> { try { await prisma.$queryRaw`SELECT 1`; return "ok"; } catch { return "error"; } } /** * Lightweight Redis PING check using a raw TCP socket. * Avoids importing ioredis (which is only a dependency of @capakraken/api). */ async function checkRedis(): Promise<"ok" | "error"> { return new Promise((resolve) => { try { const url = new URL(REDIS_URL); const host = url.hostname || "localhost"; const port = parseInt(url.port || "6379", 10); const timeout = 3000; const socket = createConnection({ host, port }, () => { // Send Redis PING command using RESP protocol socket.write("*1\r\n$4\r\nPING\r\n"); }); socket.setTimeout(timeout); socket.on("data", (data) => { const response = data.toString(); socket.destroy(); // Redis responds with +PONG\r\n resolve(response.includes("PONG") ? "ok" : "error"); }); socket.on("timeout", () => { socket.destroy(); resolve("error"); }); socket.on("error", () => { socket.destroy(); resolve("error"); }); } catch { resolve("error"); } }); } export async function GET() { const [postgres, redis] = await Promise.all([ checkPostgres(), checkRedis(), ]); const allHealthy = postgres === "ok" && redis === "ok"; return NextResponse.json( { status: allHealthy ? "ready" : "not_ready", postgres, redis, }, { status: allHealthy ? 200 : 503 }, ); }