Skip to content

Sharded cluster pub/sub resubscribe fails with CROSSSLOT error #2902

Open
@albertxing

Description

@albertxing

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:

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

Logs

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions