import { Controller, Get, Res } from "@nestjs/common"; import { ApiTags, ApiOperation } from "@nestjs/swagger"; import type { Response } from "express"; import { Public } from "../../common/decorators"; import { PrismaService } from "../../database/prisma.service"; import { PredictionsService } from "../predictions/predictions.service"; @ApiTags("Health") @Controller("health") export class HealthController { constructor( private prisma: PrismaService, private readonly predictionsService: PredictionsService, ) {} @Get() @Public() @ApiOperation({ summary: "Basic health check" }) async check(@Res() response: Response) { const database = await this.getDatabaseHealth(); const aiEngine = await this.predictionsService.checkHealth(); const ok = database.status === "up" && aiEngine.predictionServiceReady; return response.status(ok ? 200 : 503).json({ status: ok ? "ok" : "degraded", timestamp: new Date().toISOString(), checks: { database, aiEngine, }, }); } @Get("ready") @Public() @ApiOperation({ summary: "Readiness check (includes database)" }) async readiness(@Res() response: Response) { const database = await this.getDatabaseHealth(); const aiEngine = await this.predictionsService.checkHealth(); const ready = database.status === "up" && aiEngine.predictionServiceReady; return response.status(ready ? 200 : 503).json({ status: ready ? "ready" : "not_ready", timestamp: new Date().toISOString(), checks: { database, aiEngine, }, }); } @Get("live") @Public() @ApiOperation({ summary: "Liveness check" }) liveness(@Res() response: Response) { return response .status(200) .json({ status: "ok", timestamp: new Date().toISOString() }); } @Get("dependencies") @Public() @ApiOperation({ summary: "Dependency-level health details" }) async dependencies(@Res() response: Response) { const database = await this.getDatabaseHealth(); const aiEngine = await this.predictionsService.checkHealth(); return response.status(200).json({ timestamp: new Date().toISOString(), checks: { database, aiEngine, }, }); } private async getDatabaseHealth() { try { await this.prisma.$queryRaw`SELECT 1`; return { status: "up", }; } catch (error: unknown) { return { status: "down", detail: error instanceof Error ? error.message : "Unknown database error", }; } } }