import { Inject, Injectable, type OnModuleDestroy } from "@nestjs/common"; import { createClient, type RedisClientType } from "redis"; import { PrismaService } from "../database/prisma.service.js"; import { DomainException } from "../common/domain.exception.js"; import { ErrorCode } from "@drift/contracts"; import { HttpStatus } from "@nestjs/common"; @Injectable() export class HealthService implements OnModuleDestroy { private readonly redis: RedisClientType; get redisClient(): RedisClientType { return this.redis; } constructor(@Inject(PrismaService) private readonly prisma: PrismaService) { this.redis = createClient({ url: process.env.REDIS_URL ?? "redis://127.0.0.1:6379", socket: { connectTimeout: 500, reconnectStrategy: false }, }); this.redis.on("error", () => undefined); } async check(): Promise<{ status: "ok"; postgres: "up"; redis: "up" }> { try { if (!this.redis.isOpen) await this.redis.connect(); await Promise.all([this.prisma.$queryRaw`SELECT 1`, this.redis.ping()]); return { status: "ok", postgres: "up", redis: "up" }; } catch { throw new DomainException( ErrorCode.SERVICE_UNAVAILABLE, "Dependencies unavailable", HttpStatus.SERVICE_UNAVAILABLE, ); } } async onModuleDestroy(): Promise { if (this.redis.isOpen) await this.redis.quit(); } }