UNPKG

hikma-engine

Version:

Code Knowledge Graph Indexer - A sophisticated TypeScript-based indexer that transforms Git repositories into multi-dimensional knowledge stores for AI agents

195 lines (194 loc) 6.92 kB
"use strict"; /** * @file Health check routes for monitoring API server status. * Provides endpoints to check server health and database connectivity. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.createHealthRouter = createHealthRouter; const express_1 = require("express"); const logger_1 = require("../../utils/logger"); const config_1 = require("../../config"); const logger = (0, logger_1.getLogger)('HealthRouter'); /** * Checks database connectivity status. */ async function checkDatabaseHealth() { const startTime = Date.now(); try { const config = (0, config_1.getConfig)(); const dbConfig = config.getDatabaseConfig(); // For now, we'll do basic checks on database paths/URLs // In a full implementation, we would actually test connections // Check if database paths are accessible (for file-based databases) const fs = require('fs'); const path = require('path'); // Check SQLite database directory exists const sqliteDir = path.dirname(dbConfig.sqlite.path); if (!fs.existsSync(sqliteDir)) { return { status: 'unhealthy', error: `SQLite database directory does not exist: ${sqliteDir}`, }; } const responseTime = Date.now() - startTime; return { status: 'healthy', responseTime, }; } catch (error) { const responseTime = Date.now() - startTime; return { status: 'unhealthy', responseTime, error: error.message, }; } } /** * Checks memory usage status. */ function checkMemoryHealth() { const memUsage = process.memoryUsage(); const totalMemory = require('os').totalmem(); const memoryPercentage = (memUsage.rss / totalMemory) * 100; return { status: memoryPercentage > 90 ? 'unhealthy' : 'healthy', usage: { rss: Math.round(memUsage.rss / 1024 / 1024), // MB heapTotal: Math.round(memUsage.heapTotal / 1024 / 1024), // MB heapUsed: Math.round(memUsage.heapUsed / 1024 / 1024), // MB external: Math.round(memUsage.external / 1024 / 1024), // MB }, percentage: Math.round(memoryPercentage * 100) / 100, }; } /** * Creates the health check router. */ function createHealthRouter() { const router = (0, express_1.Router)(); /** * Basic health check endpoint. * GET /health */ router.get('/', async (req, res) => { try { const startTime = Date.now(); // Perform health checks const databaseCheck = await checkDatabaseHealth(); const memoryCheck = checkMemoryHealth(); // Determine overall status let overallStatus = 'healthy'; if (databaseCheck.status === 'unhealthy') { overallStatus = 'unhealthy'; } else if (memoryCheck.status === 'unhealthy') { overallStatus = 'degraded'; } const response = { success: true, data: { status: overallStatus, timestamp: new Date().toISOString(), uptime: Math.floor(process.uptime()), version: process.env.npm_package_version || '1.0.0', environment: process.env.NODE_ENV || 'development', checks: { database: databaseCheck, memory: memoryCheck, }, }, meta: { timestamp: new Date().toISOString(), requestId: req.headers['x-request-id'] || 'unknown', }, }; const processingTime = Date.now() - startTime; logger.debug('Health check completed', { status: overallStatus, processingTime: `${processingTime}ms`, requestId: req.headers['x-request-id'], }); // Set appropriate HTTP status code const statusCode = overallStatus === 'healthy' ? 200 : overallStatus === 'degraded' ? 200 : 503; res.status(statusCode).json(response); } catch (error) { logger.error('Health check failed', { error: error.message, requestId: req.headers['x-request-id'], }); res.status(500).json({ success: false, error: { code: 'HEALTH_CHECK_FAILED', message: 'Health check failed', }, meta: { timestamp: new Date().toISOString(), requestId: req.headers['x-request-id'] || 'unknown', }, }); } }); /** * Liveness probe endpoint (simple check that server is running). * GET /health/live */ router.get('/live', (req, res) => { res.status(200).json({ success: true, data: { status: 'alive', timestamp: new Date().toISOString(), }, meta: { timestamp: new Date().toISOString(), requestId: req.headers['x-request-id'] || 'unknown', }, }); }); /** * Readiness probe endpoint (check if server is ready to handle requests). * GET /health/ready */ router.get('/ready', async (req, res) => { try { const databaseCheck = await checkDatabaseHealth(); const isReady = databaseCheck.status === 'healthy'; res.status(isReady ? 200 : 503).json({ success: true, data: { status: isReady ? 'ready' : 'not_ready', timestamp: new Date().toISOString(), checks: { database: databaseCheck, }, }, meta: { timestamp: new Date().toISOString(), requestId: req.headers['x-request-id'] || 'unknown', }, }); } catch (error) { logger.error('Readiness check failed', { error: error.message, requestId: req.headers['x-request-id'], }); res.status(503).json({ success: false, error: { code: 'READINESS_CHECK_FAILED', message: 'Readiness check failed', }, meta: { timestamp: new Date().toISOString(), requestId: req.headers['x-request-id'] || 'unknown', }, }); } }); return router; }