import { Controller, Get, Inject } from '@nestjs/common'; import type { HealthResponse } from '@siop/shared'; import Redis from 'ioredis'; import { Public } from '../auth/public.decorator'; import { loadEnv } from '../config/env'; import { FILE_STORAGE, type FileStorage } from '../files/file-storage'; import { PrismaService } from '../prisma/prisma.service'; @Controller('health') export class HealthController { constructor( private readonly prisma: PrismaService, @Inject(FILE_STORAGE) private readonly storage: FileStorage, ) {} @Public() @Get() async health(): Promise { const [database, redis, storage] = await Promise.all([ this.check(() => this.prisma.$queryRaw`SELECT 1`), this.check(async () => { const client = new Redis(loadEnv().REDIS_URL, { lazyConnect: true, maxRetriesPerRequest: 0, connectTimeout: 2000, }); try { await client.connect(); await client.ping(); } finally { client.disconnect(); } }), this.check(() => this.storage.healthCheck()), ]); const services = { database, redis, storage }; return { status: Object.values(services).every((s) => s === 'up') ? 'ok' : 'degraded', services, }; } private async check(fn: () => Promise): Promise<'up' | 'down'> { try { await fn(); return 'up'; } catch { return 'down'; } } }