SPB Git forge
38commits 1branches 0releases
338.7 MBsize
maindefault branch
3 h agolast push
HTML 53.9% TypeScript 44.5% JavaScript 0.6% SQL 0.5%
1.7 KB · 47 lines typescript
Raw Blame History
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