Skip to content

Server-Side Event "connection" not fired/called on Client-Connection (using wild-card namespaces) #4677

@s3cc0

Description

@s3cc0

Describe the bug
We use socket.io with Google Cloud Run with with redis-adapter for exchanging data across node-cluster and multiple containers. The challenge is that Google Cloud Run kills the connections every 60min, we don't use sticky extension as we work on websockets only ourselves. Thus do not support polling. When scaling the containers no matter in which direction, it happens from time to time that the client gets a socket connection, but from server the event "connection" is not called. As a result, all other events on the socket itself do not work.

Important: We use Namespaces and Channels

To Reproduce

  1. create a system with multiple servers and node-cluster
  2. use redis-adapter for exchange between all nodes
  3. just connect with the clients, simulate disconnects, or wait for normal disconnect from server (tcp)
  4. sometimes it works sometimes not, connection will not fired

Version for frontend and backend:
"@socket.io/admin-ui": "^0.5.1",
"@socket.io/redis-adapter": "^8.1.0",
"redis": "^4.6.5",
"socket.io": "^4.6.1",
"socket.io-client": "^4.6.1",

Redis Server 6.x+ (issue also with redis server 4.x+)

Server
Code Example

import { Server } from "socket.io";
/* ... */
// initialize socket io
const io = new Server(app.http, {
    noServer: true,
    cors: {
        origin: "*",
        methods: ["GET", "POST"],
        credentials: true
    }
});
const redisPub = activeRedisClient.duplicate();
await redisPub.connect();
await redisPub.ping();
const redisSub = activeRedisClient.duplicate();
await redisSub.connect();
await redisSub.ping();
io.adapter(createAdapter(redisPub, redisSub, {
    requestsTimeout: 3000
}));

const dynamicNamespace = io.of(async (name, auth, next) => {
    next(null, true);
});
dynamicNamespace.use(async (socket, next) => { next(null); });

dynamicNamespace.on('connection', async (socket) => {
   // this event sometimes not called
    socket.on('disconnect', async () => {
        // this event sometimes not added / called
    });

    socket.on('message', async () => {
        // this event sometimes not added / called
    });
});

Client

import { io } from "socket.io-client";

const socket = io("ws://localhost:3000/", {
    transports: ['websocket'],
    auth: {
        token: 'jwt-token',
    },
});

socket.on("connect", () => {
  console.log(`connect ${socket.id}`);
});

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

Expected behavior
It is expected that the event "connection" is always called on the server. But this is not the case, so the clients can do what they want, they can not dive into the normal program landscape. However, the socket connection remains. So there is a socket connection without the event "connection" being called on the server.

Platform:

  • Device: PC, Notebook, Mac
  • OS: Windows, Linux, OSX
  • Browser: Safari (newest), Chrome (newest), Firefox (newest)

Additional context
Important, socket.io server running in google cloud run (docker container) and scale up/down up to the traffic, we had 250 connection at one container, a scale will happen at 150 open request.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions