spb/datacenterindex
Public
HTML 53.9%
TypeScript 44.5%
JavaScript 0.6%
SQL 0.5%
1import { Redis } from "ioredis";2import { getEnv } from "./env.js";34let cacheClient: Redis | null = null;5let queueClient: Redis | null = null;6let cacheDown = false;78/** Redis client for the API cache: fail fast (no offline queue) so a Redis outage never blocks a request. */9export function getCacheRedis(): Redis | null {10 if (cacheDown) return null;11 if (!cacheClient) {12 const c = new Redis(getEnv().redisUrl, { lazyConnect: true, enableOfflineQueue: false, maxRetriesPerRequest: 1, connectTimeout: 2_000, retryStrategy: (n: number) => (n > 20 ? null : Math.min(30_000, 500 * n)) });13 c.on("error", () => { /* handled by callers: null/undefined results */ });14 c.on("end", () => { cacheDown = true; });15 c.connect().catch(() => { /* retried by ioredis */ });16 cacheClient = c;17 }18 return cacheClient;19}2021/** Redis connection for BullMQ (requires maxRetriesPerRequest: null) and worker status keys. */22export function getQueueRedis(): Redis {23 if (!queueClient) {24 const c = new Redis(getEnv().redisUrl, { lazyConnect: true, maxRetriesPerRequest: null, enableOfflineQueue: true, connectTimeout: 3_000 });25 c.on("error", () => { /* surfaced through BullMQ / ops calls */ });26 queueClient = c;27 }28 return queueClient;29}3031export async function redisPing(): Promise<boolean> {32 try {33 const r = getQueueRedis();34 if (r.status === "wait") await r.connect().catch(() => {});35 const pong = await Promise.race([r.ping(), new Promise<string>((_, rej) => setTimeout(() => rej(new Error("timeout")), 1500))]);36 return pong === "PONG";37 } catch {38 return false;39 }40}4142export async function closeRedis(): Promise<void> {43 await Promise.allSettled([cacheClient?.quit(), queueClient?.quit()]);44 cacheClient = null;45 queueClient = null;46}47