feat: Healthcheck-Endpunkt für Reverse-Proxy und Monitoring
/api/health prüft die Datenbankverbindung mit und antwortet bei Ausfall mit 503 — eine App ohne Datenbank ist nicht gesund, auch wenn der Prozess läuft.
This commit is contained in:
@@ -0,0 +1,34 @@
|
|||||||
|
import { NextResponse } from "next/server";
|
||||||
|
import { prisma } from "@/lib/db";
|
||||||
|
import pkg from "../../../../package.json";
|
||||||
|
|
||||||
|
export const dynamic = "force-dynamic";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Healthcheck für Reverse-Proxy und Uptime-Monitoring.
|
||||||
|
* Prüft die Datenbankverbindung mit — eine App ohne DB ist nicht gesund.
|
||||||
|
*/
|
||||||
|
export async function GET() {
|
||||||
|
const startedAt = Date.now();
|
||||||
|
try {
|
||||||
|
await prisma.$queryRaw`SELECT 1`;
|
||||||
|
return NextResponse.json({
|
||||||
|
status: "ok",
|
||||||
|
version: pkg.version,
|
||||||
|
database: "ok",
|
||||||
|
latencyMs: Date.now() - startedAt,
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{
|
||||||
|
status: "error",
|
||||||
|
version: pkg.version,
|
||||||
|
database: "unreachable",
|
||||||
|
message: error instanceof Error ? error.message : "unbekannter Fehler",
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
},
|
||||||
|
{ status: 503 },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
+24
-6
@@ -1,7 +1,11 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "ES2022",
|
"target": "ES2022",
|
||||||
"lib": ["dom", "dom.iterable", "esnext"],
|
"lib": [
|
||||||
|
"dom",
|
||||||
|
"dom.iterable",
|
||||||
|
"esnext"
|
||||||
|
],
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
@@ -11,14 +15,28 @@
|
|||||||
"moduleResolution": "bundler",
|
"moduleResolution": "bundler",
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
"jsx": "preserve",
|
"jsx": "react-jsx",
|
||||||
"incremental": true,
|
"incremental": true,
|
||||||
"noUncheckedIndexedAccess": true,
|
"noUncheckedIndexedAccess": true,
|
||||||
"plugins": [{ "name": "next" }],
|
"plugins": [
|
||||||
|
{
|
||||||
|
"name": "next"
|
||||||
|
}
|
||||||
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"@/*": ["./src/*"]
|
"@/*": [
|
||||||
|
"./src/*"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
"include": [
|
||||||
"exclude": ["node_modules"]
|
"next-env.d.ts",
|
||||||
|
"**/*.ts",
|
||||||
|
"**/*.tsx",
|
||||||
|
".next/types/**/*.ts",
|
||||||
|
".next/dev/types/**/*.ts"
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"node_modules"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user