Spaces:
Paused
Paused
File size: 4,117 Bytes
529090e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 | import { Router } from 'express';
import { neo4jService } from '../database/Neo4jService';
import { checkPrismaConnection, prisma } from '../database/prisma';
const router = Router();
/**
* Overall system health check
*/
router.get('/health', async (req, res) => {
const health = {
status: 'healthy',
timestamp: new Date().toISOString(),
services: {
database: 'unknown',
neo4j: 'unknown',
redis: 'unknown',
},
uptime: process.uptime(),
memory: process.memoryUsage(),
};
try {
// Check Prisma/PostgreSQL
const prismaHealthy = await checkPrismaConnection();
health.services.database = prismaHealthy ? 'healthy' : 'unhealthy';
if (!prismaHealthy) health.status = 'degraded';
} catch {
health.services.database = 'unhealthy';
health.status = 'degraded';
}
try {
// Check Neo4j
await neo4jService.connect();
const neo4jHealthy = await neo4jService.healthCheck();
health.services.neo4j = neo4jHealthy ? 'healthy' : 'unhealthy';
await neo4jService.disconnect();
if (!neo4jHealthy) {
health.status = 'degraded';
}
} catch (error) {
health.services.neo4j = 'unhealthy';
health.status = 'degraded';
}
// Check Redis
if (process.env.REDIS_URL) {
// Redis URL is configured but ioredis client is not yet installed
// Once ioredis is installed, this can be updated to perform actual health check
health.services.redis = 'configured_but_client_unavailable';
} else {
health.services.redis = 'not_configured';
}
const statusCode = health.status === 'healthy' ? 200 : 503;
res.status(statusCode).json(health);
});
/**
* Database-specific health check
*/
router.get('/health/database', async (req, res) => {
try {
const prismaHealthy = await checkPrismaConnection();
if (!prismaHealthy) {
return res.status(503).json({
status: 'unhealthy',
error: 'Prisma unreachable',
});
}
const result = await prisma.$queryRaw`SELECT 1 as test`;
res.json({
status: 'healthy',
type: 'PostgreSQL (Prisma)',
tables: 'n/a',
test: (result as any[])[0]?.test === 1,
});
} catch (error) {
res.status(503).json({
status: 'unhealthy',
error: String(error),
});
}
});
/**
* Neo4j-specific health check
*/
router.get('/health/neo4j', async (req, res) => {
try {
await neo4jService.connect();
const healthy = await neo4jService.healthCheck();
if (healthy) {
const stats = await neo4jService.runQuery('MATCH (n) RETURN count(n) as nodeCount');
await neo4jService.disconnect();
res.json({
status: 'healthy',
connected: true,
nodeCount: stats[0]?.nodeCount || 0,
});
} else {
throw new Error('Health check failed');
}
} catch (error) {
res.status(503).json({
status: 'unhealthy',
connected: false,
error: String(error),
});
}
});
/**
* Readiness check (for Kubernetes)
*/
router.get('/ready', async (req, res) => {
try {
// Use Prisma connection check instead of SQLite
const prismaHealthy = await checkPrismaConnection();
if (!prismaHealthy) {
throw new Error('Database not ready');
}
res.json({
status: 'ready',
timestamp: new Date().toISOString(),
});
} catch (error) {
res.status(503).json({
status: 'not_ready',
error: String(error),
});
}
});
/**
* Liveness check (for Kubernetes)
*/
router.get('/live', (req, res) => {
res.json({
status: 'alive',
timestamp: new Date().toISOString(),
uptime: process.uptime(),
});
});
export default router;
|