import IORedis from 'ioredis'; import logger from '@utils/logger'; const redisUrl = process.env.REDIS_URL || 'redis://localhost:6379'; const redisPassword = process.env.REDIS_PASSWORD || undefined; // Throttle Redis error/close logs when Redis is down (avoid flooding terminal) let lastRedisErrorLog = 0; let lastRedisCloseLog = 0; const REDIS_LOG_INTERVAL_MS = 2 * 60 * 1000; // 2 minutes const redisOptions: any = { maxRetriesPerRequest: null, // Required for BullMQ enableReadyCheck: false, retryStrategy: (times: number) => { if (times > 5) { if (Date.now() - lastRedisErrorLog >= REDIS_LOG_INTERVAL_MS) { lastRedisErrorLog = Date.now(); logger.error('[Redis] Connection failed after 5 attempts. TAT/Pause-Resume need Redis. Start Redis or ignore if not needed.'); } return null; } return Math.min(times * 2000, 10000); }, connectTimeout: 30000, commandTimeout: 20000, keepAlive: 30000, autoResubscribe: true, autoResendUnfulfilledCommands: true }; if (redisPassword) { redisOptions.password = redisPassword; logger.info('[Redis] Using password authentication'); } let sharedConnection: IORedis | null = null; // Create a SINGLE shared connection for both Queue and Worker export const getSharedRedisConnection = (): IORedis => { if (!sharedConnection) { logger.info(`[Redis] Connecting to ${redisUrl}`); sharedConnection = new IORedis(redisUrl, redisOptions); sharedConnection.on('connect', () => { logger.info(`[Redis] ✅ Connected successfully`); }); sharedConnection.on('error', (err) => { const now = Date.now(); if (now - lastRedisErrorLog >= REDIS_LOG_INTERVAL_MS) { lastRedisErrorLog = now; logger.error('[Redis] Connection error: ' + err.message + ' (next log in 2 min if still down)'); } }); sharedConnection.on('close', () => { const now = Date.now(); if (now - lastRedisCloseLog >= REDIS_LOG_INTERVAL_MS) { lastRedisCloseLog = now; logger.warn('[Redis] Connection closed (next log in 2 min if still down)'); } }); } return sharedConnection; }; // Export for backwards compatibility export const sharedRedisConnection = getSharedRedisConnection(); export default sharedRedisConnection;