socketio / socket.io-redis-adapter

Adapter to enable broadcasting of events to multiple separate socket.io server nodes.
https://socket.io/docs/v4/redis-adapter/
MIT License
2.74k stars 489 forks source link

How to count clients in a room across all instances #507

Open sgtraptor opened 1 year ago

sgtraptor commented 1 year ago

Hi, I have a problem with counting all clients connected to a specific room. We are using Redis adapter and we seem to be getting different results on both of our ECS tasks. I can call io.of("/").adapter.rooms.get(hash) but it seems to count clients in this room within one of the tasks. How can I get a number of clients connected to a room across all instances?

I've checked socket.io and socket.io redis adapter reference twice and I haven't found a proper solution. Sorry if this is dumb question, but nothing seems to work and this seems to me like an obvious "should be there" feature that probably is already implemented but I can't seem to find it.

darrachequesne commented 1 year ago

Hi! There are a couple of ways to do this:

const sockets = await io.in("my-room").fetchSockets();

console.log(sockets.length);

Reference: https://socket.io/docs/v4/server-api/#serverfetchsockets

This is not the most efficient way, because it returns some additional attributes (id, handshake, rooms, data) for each socket, but this also allows to count the number of distinct users:

const sockets = await io.in("my-room").fetchSockets();
const userIds = new Set();

sockets.forEach((socket) => {
  userIds.add(socket.data.userId);
});

console.log(userIds.size);
io.serverSideEmit("socketsCount", "my-room", (err, responses) => {
  const localCount = io.of("/").adapter.rooms.get("my-room").size;
  const totalCount = responses.reduce((acc, value) => acc + value, localCount);

  console.log(totalCount);
});

io.on("socketsCount", (room, cb) => {
  const count = io.of("/").adapter.rooms.get(room).size;
  cb(count);
});

Reference: https://socket.io/docs/v4/server-api/#serverserversideemiteventname-args

nikunjxsquads commented 1 month ago

i have node server running on kubernet cluster with 2 pods now i have 10 users 5 users connected in pod 1 and another 5 is connected on pod2 i have use redis adapter now i have no issue when i send message using user socket id from pod1 to pod2 but i have one module that pod create one socket room and join 3 users from pod 1 and 3 users from pod2 when that room something is changed and that pod1 broadcast with that created room only pod1 users getting data pod joined socket room users can't getting data what is the solution?

darrachequesne commented 1 month ago

@nikunjxsquads I'm not sure to understand your issue, the Redis adapter should be sufficient to forward the events between the pods.

Could you please create a sample project reproducing the issue? You can start from the fiddle here: https://github.com/socketio/socket.io-fiddle