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; ping(): Promise; quit(): Promise; } export class RedisHealthClient implements OnModuleDestroy { constructor(private readonly client: RedisPingPort) {} async check(): Promise { 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 { if ( this.client.status !== 'wait' && this.client.status !== 'end' && this.client.status !== 'close' ) { await this.client.quit(); } } async onModuleDestroy(): Promise { 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); }