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

Is elasticache cluster mode supported with node-redis? #553

Open
jlippold opened this issue Nov 24, 2024 · 3 comments
Open

Is elasticache cluster mode supported with node-redis? #553

jlippold opened this issue Nov 24, 2024 · 3 comments

Comments

@jlippold
Copy link

When using this package with node-redis, I get the following error

node:internal/process/promises:289
            triggerUncaughtException(err, true /* fromPromise */);
            ^

[ErrorReply: ERR unknown command 'psubscribe', with args beginning with: socket.io#/#*]

The only related issue I can find, is this one which describes switching to io-redis over node-redis when using elasticache for cluster mode. #484

This issue in node-redis says support was added: redis/node-redis#2065 but they don't really give any documention on how to use it.

Does this package support node-redis with Elasticache in AWS? I'm running Redis OSS cluster serverless. Thanks for the help

"socket.io": "^4.7.5",
"@socket.io/redis-adapter": "^8.3.0",
"@socket.io/redis-emitter": "^5.1.0",
"redis": "^4.7.0",

Here's a code snippet of my current socket implementation which does throws the error

const { Server } = require("socket.io");
const { createAdapter } = require("@socket.io/redis-adapter");
const { Emitter } = require("@socket.io/redis-emitter");
const { createClient } = require("redis");
const redis = require('../../configs/redis');
const env = process.env.NODE_ENV || 'local';

const host = redis[env].host || '127.0.0.1';
const port = redis[env].port || 6379;

let io = null;
let emitter = null;

function startServer(server) {

    const pubClient = createClient({
            url: `rediss://${host}:${port}`, // rediss:// is the secure version of redis://
    });
    const subClient = pubClient.duplicate();
    const tasks = [
        pubClient.connect(), subClient.connect()
    ];

    Promise.all(tasks).then(() => {

        emitter = new Emitter(pubClient);

        const serverOptions = {
            adapter: createAdapter(pubClient, subClient, {
                key: adapterKey,
                requestsTimeout: 10000
            }),
            connectionStateRecovery: {
                maxDisconnectionDuration: 2 * 60 * 1000, // the backup duration of the sessions and the packets
                skipMiddlewares: true, // whether to skip middlewares upon successful recovery
            },
            cors: {
                origin: [
                    'http://localhost:8080',
                    'http://localhost:3000',
                    'http://localhost',
                ]
            }
        };

        io = new Server(server, serverOptions);

        io.on('connection', (socket) => {
            console.log(`WebSocket connection established: socket.id ${socket.id} for ${ioKey}`);

            socket.on('error', function (err) {
                console.error('Socket error', err);
            });

        });

        io.on('socketMessage', (data) => {
             console.log(`${ioKey} received socketMessage`); // Logs all clusters that received the message
        });

        io.on('error', (err) => {
            console.error('WebSocket server error', err);
        });

        io.on('close', () => {
            console.error('WebSocket server closed');
        });

        io.engine.on("connection_error", (err) => {
            console.error('WebSocket connection error', err); // See https://socket.io/docs/v4/troubleshooting-connection-issues
        });

    }).catch((err) => {
        console.error('FATAL: Could not start Socket.io server with redis adapter', err);
    });

}

Thanks for the help

@vanics
Copy link

vanics commented Jan 4, 2025

I am also facing this issue. Have you come across a solution @jlippold ?

@jlippold
Copy link
Author

jlippold commented Jan 4, 2025

Nah bro, I switched to io-redis instead

@darrachequesne
Copy link
Member

Hi! I was not able to reproduce the issue:

Elasticache with cluster mode enabled:

image

Dependencies:

$ npm ls 
[email protected] /tmp/tmp-socket.io-redis
├── @socket.io/[email protected]
├── [email protected]
└── [email protected]

My server:

const { createCluster } = require("redis");
const { Server } = require("socket.io");
const { createAdapter } = require("@socket.io/redis-adapter");

async function main() {
  const pubClient = createCluster({
    rootNodes: [
      {
        url: "redis://test02-0001-001.jrvb7m.0001.usw1.cache.amazonaws.com:6379",
      },
      {
        url: "redis://test02-0002-001.jrvb7m.0001.usw1.cache.amazonaws.com:6379",
      },
      {
        url: "redis://test02-0003-001.jrvb7m.0001.usw1.cache.amazonaws.com:6379",
      },
    ],
  });
  const subClient = pubClient.duplicate();

  await Promise.all([
    pubClient.connect(),
    subClient.connect(),
  ]);

  console.log("successful connection");

  const io = new Server({
    adapter: createAdapter(pubClient, subClient)
  });

  const io2 = new Server({
    adapter: createAdapter(pubClient, subClient)
  });

  io2.on("hello", (val) => {
    console.log("received", val);
  });

  setTimeout(() => {
    io.serverSideEmit("hello", "world");
  }, 100);
}

main().catch((err) => {
  console.error(err);
});

Output:

$ node test.js 
successful connection
received world

The serverSideEmit ensures the link between the two Socket.IO servers is properly going through the Redis cluster.

Could you please check?

Reference: https://socket.io/docs/v4/redis-adapter/#with-the-redis-package-and-a-redis-cluster

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

3 participants