feat(GOV-009): 建立后端契约与健康检查

This commit is contained in:
2026-08-13 17:26:51 +08:00
parent 3fc703de0b
commit 420aa22342
32 changed files with 1625 additions and 8 deletions
@@ -0,0 +1,58 @@
import Redis from 'ioredis';
import type { OnModuleDestroy } from '@nestjs/common';
import type { DependencyHealthDto } from '../../http-contracts/src/health.dto';
import type { RedisRuntimeConfig } from '../../config/src/runtime-config';
interface RedisPingPort {
status: string;
connect(): Promise<void>;
ping(): Promise<string>;
quit(): Promise<unknown>;
}
export class RedisHealthClient implements OnModuleDestroy {
constructor(private readonly client: RedisPingPort) {}
async check(): Promise<DependencyHealthDto> {
if (
this.client.status === 'wait' ||
this.client.status === 'end' ||
this.client.status === 'close'
) {
await this.client.connect();
}
const response = await this.client.ping();
if (response !== 'PONG') throw new Error('Redis PING 未返回 PONG');
return { status: 'healthy', detail: 'PONG' };
}
async close(): Promise<void> {
if (
this.client.status !== 'wait' &&
this.client.status !== 'end' &&
this.client.status !== 'close'
) {
await this.client.quit();
}
}
async onModuleDestroy(): Promise<void> {
await this.close();
}
}
export function createRedisHealthClient(config: RedisRuntimeConfig): RedisHealthClient {
const client = new Redis({
host: config.host,
port: config.port,
username: config.username || undefined,
password: config.password || undefined,
db: config.database,
tls: config.tls ? {} : undefined,
lazyConnect: true,
enableOfflineQueue: false,
maxRetriesPerRequest: 0,
});
return new RedisHealthClient(client);
}