chore: normalize test-server health governance

This commit is contained in:
2026-05-21 14:21:27 +08:00
parent 3b67df19e7
commit d79c11fb15
5 changed files with 96 additions and 6 deletions
+29
View File
@@ -0,0 +1,29 @@
import { describe, it, expect } from 'vitest';
import { computeOverallHealth } from './health';
describe('computeOverallHealth', () => {
it('returns ok when core services are healthy and the video parser is optional', () => {
const status = computeOverallHealth({
dbOk: true,
redisStatus: 'connected',
pansouStatus: 'ok',
videoParserStatus: 'unreachable',
});
expect(status).toBe('ok');
});
it('returns degraded when the video parser is required but unavailable', () => {
const status = computeOverallHealth(
{
dbOk: true,
redisStatus: 'connected',
pansouStatus: 'ok',
videoParserStatus: 'unreachable',
},
{ videoParserRequired: true },
);
expect(status).toBe('degraded');
});
});
+32
View File
@@ -0,0 +1,32 @@
export type HealthStatus = 'ok' | 'degraded' | 'unhealthy';
export interface HealthInputs {
dbOk: boolean;
redisStatus: string;
pansouStatus: string;
videoParserStatus: string;
}
export interface HealthOptions {
videoParserRequired?: boolean;
}
export function computeOverallHealth(
{ dbOk, redisStatus, pansouStatus, videoParserStatus }: HealthInputs,
options: HealthOptions = {},
): HealthStatus {
const videoParserRequired = options.videoParserRequired ?? false;
if (dbOk && redisStatus === 'connected' && pansouStatus === 'ok') {
if (!videoParserRequired || videoParserStatus === 'ok') {
return 'ok';
}
return 'degraded';
}
if (dbOk && redisStatus !== 'unknown' && pansouStatus !== 'unreachable') {
return 'degraded';
}
return 'unhealthy';
}
+10 -5
View File
@@ -6,6 +6,7 @@ import morgan from 'morgan';
import config from './config';
import { VERSION as version } from "./version";
import { checkStartup } from './config/startup-validator';
import { computeOverallHealth } from './health/health';
import { getDb } from './database/database';
import { connectRedis, disconnectRedis, reconnectRedis, testRedisConnection } from './middleware/cache';
import rateLimiter from './middleware/rate-limit';
@@ -104,11 +105,15 @@ app.get('/health', async (_req, res) => {
} catch { return 'unreachable'; }
})();
const overall = dbOk && redisStatus === 'connected' && pansouStatus === 'ok' && videoParserStatus === 'ok'
? 'ok'
: dbOk && redisStatus !== 'unknown' && pansouStatus !== 'unreachable'
? 'degraded'
: 'unhealthy';
const overall = computeOverallHealth(
{
dbOk,
redisStatus,
pansouStatus,
videoParserStatus,
},
{ videoParserRequired: process.env.VIDEO_PARSER_REQUIRED === 'true' },
);
res.json({
version,