Saurabh Kumar
Saurabh Kumar

Reputation: 11

Unable to send socket.io event using @socket.io/redis-emitter to server which is using @socket.io/redis-adapter internally

I have copy pasted code from documentation. Still server is not able to receive events from emitter.

server.js

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

const io = new Server({ transports: ["websocket"] });
const pubClient = createClient({ url: "redis://localhost:6379" });
const subClient = pubClient.duplicate();

Promise.all([
  pubClient.connect(),
  subClient.connect(),
]).then(() => {
  io.adapter(createAdapter(pubClient, subClient));
  io.on("connection", (socket) => {
    console.log("socket connected");
    socket.on("time", (data) => {
      console.log("data", data);
    });
  });
  io.listen(3000);
});

emitter.js

const { Emitter } = require("@socket.io/redis-emitter");
const { createClient } = require("redis"); // not included, needs to be explicitly installed

const redisClient = createClient({ url: "redis://localhost:6379" });
const emitter = new Emitter(redisClient);

redisClient.connect().then(() => {
  const io = new Emitter(redisClient);

  setInterval(() => {
    io.emit("time", new Date());
  }, 5000);
});

Tried everything still not able to receive events on server. Events are successfully coming on redis but not propagating to server.

  1. Used namespaces
  2. Changed packages

Upvotes: 1

Views: 98

Answers (1)

Robins Gupta
Robins Gupta

Reputation: 3153

You are thinking of the server as a client and trying to listen to the event in the server adapter but actually, the socket that will receive the emitter will be the client which is connected with the Redis adapter.

In Socket.IO data flow happens in this way.

Socket.IO Data flow Diagram using adapter

Here the emitter is supposed to send the message to a topic to all the socket's server connected with redis adapter. Redis adapter will be the one connected with clients and will forward the event to socket server using redis pub-sub. Socket servers then will redirect the message to topic provided on which clients are currently connected.

The actual code will be like:

Socket Adapter

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

const pubClient = createClient({ url: "redis://localhost:6379" });
const subClient = pubClient.duplicate();

const io = new Server();
pubClient.on("connect", () => {
  console.log("pubs connected");
});

subClient.on("connect", () => {
  console.log("subs connected");
});

Promise.all([pubClient.connect(), subClient.connect()]).then(() => {
  io.adapter(createAdapter(pubClient, subClient));

  io.on("connection", (socket) => {
    console.log("Client connected with socket.server");
    socket.on("time", (arg) => {
      console.log("Hey Client.."); // world
    });
  });
  io.listen(3000);
});

Socket Emitter

const { Emitter } = require("@socket.io/redis-emitter");
const { createClient } = require("redis");

const connect = async () => {
  const redisClient = createClient({ url: "redis://localhost:6379" });
  redisClient.on("connect", () => {
    console.log("connected");
  });



  await redisClient.connect();
  const io = new Emitter(redisClient);

  setInterval(() => {
    console.log("Calling..");
    io.emit("time", new Date());
  }, 5000);
};

connect().catch(console.error);

Socket Client

<!DOCTYPE html>
<html>
  <head>
    <title>Socket Client</title>
    <script src="https://cdn.socket.io/4.5.4/socket.io.min.js"></script>
    <script>
      const socket = io("ws://localhost:3000", { transports: ["websocket"] });
      socket.on("connect", () => {
        console.log(socket.id); // x8WIv7-mJelg7on_ALbx
      });

      socket.on("disconnect", () => {
        console.log(socket.id); // undefined
      });

      socket.on("time", (arg) => {
        console.log("Hey... I am receiving message from server", arg); // world
      });
    </script>
  </head>
  <body></body>
</html>

Upvotes: 1

Related Questions