Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ssubscribe within a cluster is not working properly #1759

Open
darrachequesne opened this issue May 13, 2023 · 7 comments
Open

ssubscribe within a cluster is not working properly #1759

darrachequesne opened this issue May 13, 2023 · 7 comments

Comments

@darrachequesne
Copy link
Contributor

Hi! It seems there is an issue with the spublish()/ssubscribe() methods added in 6285e80:

import { Cluster } from "ioredis";

const clusterNodes = [
  {
    host: "localhost",
    port: 7000,
  },
  {
    host: "localhost",
    port: 7001,
  },
  {
    host: "localhost",
    port: 7002,
  },
  {
    host: "localhost",
    port: 7003,
  },
  {
    host: "localhost",
    port: 7004,
  },
  {
    host: "localhost",
    port: 7005,
  },
];

const pubClient = new Cluster(clusterNodes);
const subClient = pubClient.duplicate();

subClient.ssubscribe("foo", () => {
  pubClient.spublish("foo", "bar");
});

subClient.on("smessage", (_, message) => {
  console.log("got", message); // never received
});

The smessage event is not received. It works with classic publish()/subscribe() though:

subClient.subscribe("foo", () => {
  pubClient.publish("foo", "bar");
});

subClient.on("message", (_, message) => {
  console.log("got", message); // prints "got bar"
});

My docker-compose.yml, for reproducibility:

services:
  redis-cluster:
    image: grokzen/redis-cluster:7.0.10
    ports:
      - "7000-7005:7000-7005"

The test case here looks a bit weird, shouldn't it be something like:

const pub = new Cluster(options);
const ssub = new Cluster(options);

ssub.ssubscribe("test cluster", function () {
  pub.spublish("test shard channel", "hi");

  // node1.write(node1.findClientByName("ioredis-cluster(subscriber)"), [
  //   "smessage",
  //   "test shard channel",
  //   "hi",
  // ]);
});

Thanks in advance!

@luin
Copy link
Collaborator

luin commented May 19, 2023

Thanks for raising this up! Yeah we currently don't route messages to the right node and also don't subscribe to the right node. Should think about a solution for that.

@NurimOnsemiro
Copy link

I'm facing the same problem, I'm not getting the 'smessage' event when I register the sSubscribe function.

@NurimOnsemiro
Copy link

With a total of 3 Redis servers (ports 6379, 6380, 6381) deployed in a Redis Cluster using Docker Compose, I executed the code below.

import { Cluster, Redis } from 'ioredis'

async function getRedisClient(): Promise<Cluster> {
  return new Promise(async (resolve, reject) => {
    const redisClient = new Redis.Cluster([
      {
        host: 'localhost',
        port: 6379
      }
  ], {
      scaleReads: 'slave',
      retryDelayOnMoved: 100,
      redisOptions: {
        username: 'default',
        password: 'redispw',
        tls: undefined
      },
    })
    redisClient.on('error', (err: Error) => {
      console.error('[Ioredis] on ERROR', err)
    })
    redisClient.on('connect', async () => {
      console.log('Redis cluster connected')
      resolve(redisClient)
    })
  })
}

async function main() {
  const publisher = await getRedisClient()
  const subscriber = await getRedisClient()

  subscriber.on('smessage', (channel: string, message: string) => {
    console.log('smessage', channel, message)
  })

  subscriber.on('message', (channel: string, message: string) => {
    console.log('message', channel, message)
  })

  await subscriber.ssubscribe('hello1') // Too many redirection error (127.0.0.1:6380)
  await subscriber.ssubscribe('hello2') // Too many redirection error (127.0.0.1:6381)
  await subscriber.ssubscribe('hello3') // ok (127.0.0.1:6379)

  await publisher.spublish('hello3', '{"name": "honsemiro"}')
}
main()

Of these, only the 'hello3' channel was successful in subscribing to the shard channel. My guess is that there are different shards that are assigned based on the checksum value, and that's why it subscribes to certain shards and not others. Here's the error message.

Redis cluster connected
Redis cluster connected
c:\Users\<redacted>\Documents\nodejs\tsc_test_01\node_modules\ioredis\built\cluster\index.js:508
            handlers.maxRedirections(new Error("Too many Cluster redirections. Last error: " + error));
                                     ^
Error: Too many Cluster redirections. Last error: ReplyError: MOVED 11613 127.0.0.1:6381
    at EventEmitter.handleError (c:\Users\<redacted>\Documents\nodejs\tsc_test_01\node_modules\ioredis\built\cluster\index.js:508:38)
    at Command.command.reject (c:\Users\<redacted>\Documents\nodejs\tsc_test_01\node_modules\ioredis\built\cluster\index.js:362:23)
    at EventEmitter.handleReconnection (c:\Users\<redacted>\Documents\nodejs\tsc_test_01\node_modules\ioredis\built\Redis.js:509:30)
    at DataHandler.returnError (c:\Users\<redacted>\Documents\nodejs\tsc_test_01\node_modules\ioredis\built\DataHandler.js:41:20)
    at JavascriptRedisParser.returnError (c:\Users\<redacted>\Documents\nodejs\tsc_test_01\node_modules\ioredis\built\DataHandler.js:15:22)
    at JavascriptRedisParser.execute (c:\Users\<redacted>\Documents\nodejs\tsc_test_01\node_modules\redis-parser\lib\parser.js:542:14)
    at Socket.<anonymous> (c:\Users\<redacted>\Documents\nodejs\tsc_test_01\node_modules\ioredis\built\DataHandler.js:25:20)
    at Socket.emit (node:events:513:28)
    at Socket.emit (node:domain:489:12)
    at addChunk (node:internal/streams/readable:315:12)

@m4tty-d
Copy link

m4tty-d commented Jul 23, 2023

is there any updates on this? @luin
are there any workarounds until this will be supported?

@BrentLayne
Copy link

If it's helpful to anyone reading this -- the library node-redis (v4) supports sharded pubsub commands properly (SSUBSCRIBE, SPUBLISH, SUNSUBCRIBE)

For my project I had to migrate off of ioredis and use node-redis instead because of this issue with ioredis not supporting sharded pubsub commands

@tominou
Copy link

tominou commented Jun 13, 2024

Any news about it ? I'd prefer not to migrate to node-redis.

@m4tty-d
Copy link

m4tty-d commented Jun 28, 2024

@tominou we ended up using node-redis for this part

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants