From 3190657e496b9f3621167c2917110013385ec9f6 Mon Sep 17 00:00:00 2001 From: Nikolay Karadzhov Date: Wed, 10 Sep 2025 18:12:22 +0300 Subject: [PATCH] fix(cluster): prevent infinite loop getRandomNode could end up in an infinite loop if this.masters is empty and this.replicas is empty. fixes: #3075 --- packages/client/lib/cluster/cluster-slots.spec.ts | 11 ++++++++++- packages/client/lib/cluster/cluster-slots.ts | 3 ++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/packages/client/lib/cluster/cluster-slots.spec.ts b/packages/client/lib/cluster/cluster-slots.spec.ts index bea1453037..76c4cb53fd 100644 --- a/packages/client/lib/cluster/cluster-slots.spec.ts +++ b/packages/client/lib/cluster/cluster-slots.spec.ts @@ -5,7 +5,6 @@ import RedisClusterSlots from './cluster-slots'; describe('RedisClusterSlots', () => { describe('initialization', () => { - describe('clientSideCache validation', () => { const mockEmit = ((_event: string | symbol, ..._args: any[]): boolean => true) as EventEmitter['emit']; const clientSideCacheConfig = { ttl: 0, maxEntries: 0 }; @@ -45,4 +44,14 @@ describe('RedisClusterSlots', () => { }); }); }); + + describe('getRandomNode', ()=> { + it('should not enter infinite loop when no nodes', () => { + const slots = new RedisClusterSlots({ + rootNodes: [] + }, () => true) + slots.getRandomNode() + slots.getRandomNode() + }); + }); }); diff --git a/packages/client/lib/cluster/cluster-slots.ts b/packages/client/lib/cluster/cluster-slots.ts index 8448611232..9c75b3ab4b 100644 --- a/packages/client/lib/cluster/cluster-slots.ts +++ b/packages/client/lib/cluster/cluster-slots.ts @@ -462,6 +462,7 @@ export default class RedisClusterSlots< } *#iterateAllNodes() { + if(this.masters.length + this.replicas.length === 0) return let i = Math.floor(Math.random() * (this.masters.length + this.replicas.length)); if (i < this.masters.length) { do { @@ -542,7 +543,7 @@ export default class RedisClusterSlots< this.masters[index] : this.replicas[index - this.masters.length], client = this.#createClient(node, false); - + this.pubSubNode = { address: node.address, client,