From 4799593e1ad63c0a4b943b6bf91855cefa9f7b02 Mon Sep 17 00:00:00 2001 From: "Theo N. Truong" <644650+nhtruong@users.noreply.github.com> Date: Tue, 12 Aug 2025 20:23:29 -0600 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A7=20fix:=20Redis=20cluster=20connect?= =?UTF-8?q?ion=20errors=20and=20configuration=20(#9016)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix ioredis cluster initialization to use proper node array format - Fix reconnectOnError to return numeric delay instead of boolean - Fix keyv redis cluster configuration to use proper URL objects - Resolves "undefinedms" reconnection delay errors --- api/cache/redisClients.js | 41 +++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/api/cache/redisClients.js b/api/cache/redisClients.js index 17889d24f3..b6a89cdaa5 100644 --- a/api/cache/redisClients.js +++ b/api/cache/redisClients.js @@ -38,7 +38,7 @@ if (cacheConfig.USE_REDIS) { const targetError = 'READONLY'; if (err.message.includes(targetError)) { logger.warn('ioredis reconnecting due to READONLY error'); - return true; + return 2; // Return retry delay instead of boolean } return false; }, @@ -50,24 +50,27 @@ if (cacheConfig.USE_REDIS) { ioredisClient = urls.length === 1 ? new IoRedis(cacheConfig.REDIS_URI, redisOptions) - : new IoRedis.Cluster(cacheConfig.REDIS_URI, { - redisOptions, - clusterRetryStrategy: (times) => { - if ( - cacheConfig.REDIS_RETRY_MAX_ATTEMPTS > 0 && - times > cacheConfig.REDIS_RETRY_MAX_ATTEMPTS - ) { - logger.error( - `ioredis cluster giving up after ${cacheConfig.REDIS_RETRY_MAX_ATTEMPTS} reconnection attempts`, - ); - return null; - } - const delay = Math.min(times * 100, cacheConfig.REDIS_RETRY_MAX_DELAY); - logger.info(`ioredis cluster reconnecting... attempt ${times}, delay ${delay}ms`); - return delay; + : new IoRedis.Cluster( + urls.map((url) => ({ host: url.hostname, port: parseInt(url.port, 10) || 6379 })), + { + redisOptions, + clusterRetryStrategy: (times) => { + if ( + cacheConfig.REDIS_RETRY_MAX_ATTEMPTS > 0 && + times > cacheConfig.REDIS_RETRY_MAX_ATTEMPTS + ) { + logger.error( + `ioredis cluster giving up after ${cacheConfig.REDIS_RETRY_MAX_ATTEMPTS} reconnection attempts`, + ); + return null; + } + const delay = Math.min(times * 100, cacheConfig.REDIS_RETRY_MAX_DELAY); + logger.info(`ioredis cluster reconnecting... attempt ${times}, delay ${delay}ms`); + return delay; + }, + enableOfflineQueue: cacheConfig.REDIS_ENABLE_OFFLINE_QUEUE, }, - enableOfflineQueue: cacheConfig.REDIS_ENABLE_OFFLINE_QUEUE, - }); + ); ioredisClient.on('error', (err) => { logger.error('ioredis client error:', err); @@ -148,7 +151,7 @@ if (cacheConfig.USE_REDIS) { urls.length === 1 ? createClient({ url: cacheConfig.REDIS_URI, ...redisOptions }) : createCluster({ - rootNodes: cacheConfig.REDIS_URI.split(',').map((url) => ({ url })), + rootNodes: urls.map((url) => ({ url: url.href })), defaults: redisOptions, });