NestJS: disable incremental in 6 services tsconfig.json to fix dist not emitted when nest-cli deleteOutDir conflicts with tsc tsbuildinfo. classes/iam: import HealthModule in AppModule to fix /healthz 404. classes: rewrite HealthController to Drizzle getDb from TypeORM DI. teacher-bff: add /metrics endpoint for Prometheus scraping. infra: add node/mysql/redis exporters to observability profile. mysql-exporter v0.15.1 uses command-line flags not DATA_SOURCE_NAME. prometheus: enable web.enable-lifecycle for hot reload.
55 lines
1.4 KiB
TypeScript
55 lines
1.4 KiB
TypeScript
import { Controller, Get, HttpException, HttpStatus } from "@nestjs/common";
|
||
import { sql } from "drizzle-orm";
|
||
import { getDb } from "../../config/database.js";
|
||
|
||
const SERVICE_NAME = "classes";
|
||
|
||
/**
|
||
* 健康检查端点。
|
||
*
|
||
* - GET /healthz:liveness,仅返回进程存活,不检查依赖。
|
||
* - GET /readyz:readiness,检查 DB 连接,失败返回 503。
|
||
*
|
||
* 不需要鉴权,必须在路由白名单中放行。本控制器内容在 iam / core-edu /
|
||
* content / msg / classes 五个 NestJS 服务中一致,仅 SERVICE_NAME 不同。
|
||
*/
|
||
@Controller()
|
||
export class HealthController {
|
||
@Get("healthz")
|
||
liveness(): { status: string; service: string; timestamp: string } {
|
||
return {
|
||
status: "ok",
|
||
service: SERVICE_NAME,
|
||
timestamp: new Date().toISOString(),
|
||
};
|
||
}
|
||
|
||
@Get("readyz")
|
||
async readiness(): Promise<{
|
||
status: string;
|
||
service: string;
|
||
timestamp: string;
|
||
}> {
|
||
try {
|
||
const db = getDb();
|
||
await db.execute(sql`SELECT 1`);
|
||
return {
|
||
status: "ok",
|
||
service: SERVICE_NAME,
|
||
timestamp: new Date().toISOString(),
|
||
};
|
||
} catch (error) {
|
||
throw new HttpException(
|
||
{
|
||
status: "error",
|
||
service: SERVICE_NAME,
|
||
timestamp: new Date().toISOString(),
|
||
error:
|
||
error instanceof Error ? error.message : "database unreachable",
|
||
},
|
||
HttpStatus.SERVICE_UNAVAILABLE,
|
||
);
|
||
}
|
||
}
|
||
}
|