In shard mode, close throw error "CROSSSLOT Keys in request don't hash to the same slot"
ngot opened this issue · 3 comments
I had a chance to try the new shard PubSub adapter. Mostly works good, but when enable cleanupEmptyChildNamespaces
, the close
function will throw "CROSSSLOT Keys in request don't hash to the same slot". The root cause is redis/node-redis#2502
Currently,
close() {
const channels = [this.channel, this.responseChannel];
if (this.opts.subscriptionMode === "dynamic") {
this.rooms.forEach((_sids, room) => {
const isPublicRoom = !this.sids.has(room);
if (isPublicRoom) {
channels.push(this.dynamicChannel(room));
}
});
}
// channels has at least 2 different strings, `sUnsubscribe` assumes
// they would be hashed to the same slot which is not correct.
return this.subClient.sUnsubscribe(channels);
}
A potential workaround
return Promise.all(channels.map((channel) => this.subClient.sUnsubscribe(channel)));
// return this.subClient.sUnsubscribe(channels);
Hi! Thanks for raising the issue, I'm digging into this.
According to redis/node-redis#2502 (comment), the sUnsubscribe(Array[])
assumes all the channels use "hash tags", so they are allocated to the same slot.
In socket.io-redis-adapter, there is dynamic channels, so sUnsubscribe
one by one looks more doable.
Additionally, this is the usage of iosredis, it does not support array, but spread parameters.
https://github.com/luin/ioredis/blob/a3838ae7598c7d9d3aff688923403f6176d7a393/lib/utils/RedisCommander.ts#L8356
/**
* Stop listening for messages posted to the given shard channels
* - _group_: pubsub
* - _complexity_: O(N) where N is the number of clients already subscribed to a shard channel.
* - _since_: 7.0.0
*/
sunsubscribe(callback?: Callback<unknown>): Result<unknown, Context>;
sunsubscribe(
...args: [
...shardchannels: (string | Buffer)[],
callback: Callback<unknown>
]
): Result<unknown, Context>;
sunsubscribe(
...args: [...shardchannels: (string | Buffer)[]]
): Result<unknown, Context>;