NeahStable/app/api/health/route.ts
2026-01-12 10:37:21 +01:00

79 lines
2.1 KiB
TypeScript

import { NextResponse } from 'next/server';
import { getRedisClient } from '@/lib/redis';
import { prisma } from '@/lib/prisma';
import { logger } from '@/lib/logger';
/**
* Health check endpoint
*
* Vérifie la santé de l'application et de ses dépendances:
* - Base de données PostgreSQL
* - Redis (si configuré)
*
* Usage:
* GET /api/health
*
* Réponses:
* 200: Tous les services sont opérationnels
* 503: Un ou plusieurs services sont indisponibles
*/
export async function GET() {
const startTime = Date.now();
const checks: Record<string, { status: string; message?: string; latency?: number }> = {};
let overallStatus: 'ok' | 'degraded' | 'down' = 'ok';
// Vérifier PostgreSQL
try {
const dbStart = Date.now();
await prisma.$queryRaw`SELECT 1`;
const dbLatency = Date.now() - dbStart;
checks.database = {
status: 'ok',
latency: dbLatency,
};
} catch (error) {
logger.error('[HEALTH] Database check failed', {
error: error instanceof Error ? error.message : String(error),
});
checks.database = {
status: 'error',
message: error instanceof Error ? error.message : 'Unknown error',
};
overallStatus = 'degraded';
}
// Vérifier Redis (optionnel)
try {
const redis = getRedisClient();
const redisStart = Date.now();
await redis.ping();
const redisLatency = Date.now() - redisStart;
checks.redis = {
status: 'ok',
latency: redisLatency,
};
} catch (error) {
logger.warn('[HEALTH] Redis check failed', {
error: error instanceof Error ? error.message : String(error),
});
// Redis n'est pas critique, donc on ne change pas le statut global
checks.redis = {
status: 'error',
message: error instanceof Error ? error.message : 'Unknown error',
};
}
const totalLatency = Date.now() - startTime;
const response = {
status: overallStatus,
timestamp: new Date().toISOString(),
uptime: process.uptime(),
checks,
latency: totalLatency,
};
const statusCode = overallStatus === 'ok' ? 200 : 503;
return NextResponse.json(response, { status: statusCode });
}