-
Couldn't load subscription status.
- Fork 1.9k
Description
Description
When a pub/sub client reconnects to a host after an error or a socket disconnect, it attempts to resubscribe to previously subscribed channels:
node-redis/packages/client/lib/client/pub-sub.ts
Lines 325 to 345 in 33cdc00
| resubscribe() { | |
| const commands = []; | |
| for (const [type, listeners] of Object.entries(this.listeners)) { | |
| if (!listeners.size) continue; | |
| this.#isActive = true; | |
| this.#subscribing++; | |
| const callback = () => this.#subscribing--; | |
| commands.push({ | |
| args: [ | |
| COMMANDS[type as PubSubType].subscribe, | |
| ...listeners.keys() | |
| ], | |
| channelsCounter: listeners.size, | |
| resolve: callback, | |
| reject: callback | |
| } satisfies PubSubCommand); | |
| } | |
| return commands; | |
| } |
It does this by issuing a single subscribe command with all listener channels as arguments. However, this is not valid with sharded pub/sub if the channels do not hash to the same slot, even if they are all owned by the same shard; the server will return a CROSSSLOT error (CROSSSLOT Keys in request don't hash to the same slot).
A simple solution for this might be to issue one subscribe command per channel for PubSubType.SHARDED subscriptions. However, there are some further issues with the current resubscription approach; for example, if a slot has moved between shards between the disconnect and the reconnect, the current logic won't be able to resubscribe correctly.
I'd be happy to open a PR implementing the rough solution (one command per channel) without consideration for moved slots, but would prefer if we can figure out a general solution that can handle MOVED errors as well!
Node.js Version
v23.6.1
Redis Server Version
7.4.2
Node Redis Version
4.7.0
Platform
Linux