4 * @description Health check and service testing endpoints for infrastructure monitoring. Provides status checks for llama.cpp AI service, Redis cache, and PostgreSQL database. Used by load balancers, monitoring systems, and DevOps dashboards.
5 * @see {@link ../services/llamaCppService} for llama.cpp integration
6 * @see {@link ../services/db} for database connection
7 * @see {@link ../config/redis} for Redis configuration
8 * @apiDefine HealthGroup Health
10 * @apiError (Error 500) ServerError Service test failed (for test endpoints).
13// Health check route for AI and infrastructure
14const express = require('express');
15const router = express.Router();
16const { healthCheck: llamaHealthCheck, getModelInfo } = require('../services/llamaCppService');
17const Redis = require('ioredis');
20 * @api {get} /health Health check for all services
23 * @apiDescription Comprehensive health check for all backend services including llama.cpp AI service, Redis cache, and PostgreSQL database. Always returns 200 OK to keep load balancers happy even if individual services are degraded. Use service-level status fields to determine actual health.
24 * @apiSuccess {string} status Overall status ("ok").
25 * @apiSuccess {string} timestamp Health check timestamp.
26 * @apiSuccess {object} services Service-specific health status.
27 * @apiSuccess {object} services.llamaCpp Llama.cpp AI service status.
28 * @apiSuccess {string} services.llamaCpp.status Service status (healthy, unhealthy, error).
29 * @apiSuccess {string} services.llamaCpp.endpoint Llama.cpp endpoint URL.
30 * @apiSuccess {object} [services.llamaCpp.model] Model information (if healthy).
31 * @apiSuccess {object} services.redis Redis cache status.
32 * @apiSuccess {string} services.redis.status Service status (healthy, error).
33 * @apiSuccess {Object} services.database PostgreSQL database status.
34 * @apiSuccess {string} services.database.status Service status (healthy, unhealthy, error).
35 * @apiExample {curl} Example usage:
36 * curl https://api.example.com/health
37 * @apiExample {json} Response example:
40 * "timestamp": "2026-03-12T10:30:00Z",
43 * "status": "healthy",
44 * "endpoint": "http://localhost:8080",
45 * "model": "Qwen2.5-14B-Instruct"
48 * "status": "healthy",
49 * "host": "localhost",
58router.get('/health', async (req, res) => {
61 timestamp: new Date().toISOString(),
67 const llamaHealthy = await llamaHealthCheck();
68 health.services.llamaCpp = {
69 status: llamaHealthy ? 'healthy' : 'unhealthy',
70 endpoint: process.env.LLAMA_CPP_ENDPOINT || 'http://localhost:8080'
74 const modelInfo = await getModelInfo();
76 health.services.llamaCpp.model = modelInfo;
80 health.services.llamaCpp = {
84 // Don't mark as degraded - llama.cpp might be slow to respond
85 console.warn('[Health] llama.cpp check failed:', error.message);
90 const redisConfig = require('../config/redis');
91 const redis = new Redis({
96 await redis.connect();
99 health.services.redis = {
101 host: process.env.REDIS_HOST || 'localhost',
102 port: process.env.REDIS_PORT || 6379
107 health.services.redis = {
111 // Don't mark as degraded - Redis might be initializing
112 console.warn('[Health] Redis check failed:', error.message);
115 // Check database (if DB module exists)
117 const db = require('../services/db');
118 const result = await db.query('SELECT 1 as health');
119 health.services.database = {
120 status: result ? 'healthy' : 'unhealthy'
123 health.services.database = {
127 // Don't mark as degraded - DB might be initializing
128 console.warn('[Health] Database check failed:', error.message);
131 // Always return 200 for DO health checks - the API is running
132 res.status(200).json(health);
136 * @api {post} /health/test-llama Test llama.cpp AI endpoint
139 * @apiDescription Test llama.cpp AI service by sending a sample text for rewriting. Returns the AI-generated output and endpoint information. Used for verifying AI service functionality and model responsiveness.
140 * @apiParam {string} [text="Hello, this is a test."] Test input text to send to llama.cpp.
141 * @apiSuccess {boolean} success Operation success status.
142 * @apiSuccess {string} input Input text sent to llama.cpp.
143 * @apiSuccess {string} output AI-generated output from llama.cpp.
144 * @apiSuccess {string} endpoint Llama.cpp endpoint URL.
145 * @apiError (Error 500) ServerError Llama.cpp service unreachable or error.
146 * @apiExample {curl} Example usage:
147 * curl -X POST -d '{"text":"Test message"}' https://api.example.com/health/test-llama
149router.post('/test-llama', async (req, res) => {
150 const { callLlama } = require('../services/llamaCppService');
151 const { text = 'Hello, this is a test.' } = req.body;
154 const result = await callLlama(text, 'rewrite');
159 endpoint: process.env.LLAMA_CPP_ENDPOINT
162 res.status(500).json({
164 error: error.message,
165 endpoint: process.env.LLAMA_CPP_ENDPOINT
171 * @api {get} /health/test-redis Test Redis connection
174 * @apiDescription Test Redis cache connection and functionality by performing set/get operations with a test key. Key expires after 10 seconds. Used for verifying Redis connectivity and read/write operations.
175 * @apiSuccess {boolean} success Operation success status.
176 * @apiSuccess {string} message Status message.
177 * @apiSuccess {number} testValue Value that was set and retrieved.
178 * @apiSuccess {string} host Redis host.
179 * @apiSuccess {number} port Redis port.
180 * @apiError (Error 500) ServerError Redis connection or operation failed.
181 * @apiExample {curl} Example usage:
182 * curl https://api.example.com/health/test-redis
184router.get('/test-redis', async (req, res) => {
186 const redisConfig = require('../config/redis');
187 const redis = new Redis(redisConfig);
189 const testKey = 'health:test';
190 const testValue = Date.now().toString();
192 await redis.set(testKey, testValue, 'EX', 10);
193 const retrieved = await redis.get(testKey);
201 match: testValue === retrieved,
203 host: process.env.REDIS_HOST || 'localhost',
204 port: process.env.REDIS_PORT || 6379,
205 passwordSet: !!process.env.REDIS_PASSWORD
209 res.status(500).json({
216module.exports = router;