-
Notifications
You must be signed in to change notification settings - Fork 10.1k
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
Event listeners on dynamic namespaces break when server emits on matching custom namespace before client connects #4164
Comments
Yes, this is expected, as the existing namespace has priority over the dynamic namespace. I'll update the documentation to make it clearer. |
@darrachequesne, thank you for the quick reply! We did not expect this behavior so I would just like to clarify. Given a socket.io setup with a dynamic namespace, is it expected that depending on whether a client first makes a connection or the server first emits on a child namespace, it changes the behavior? And if so, is the above mentioned example bad practice? We currently have a setup where the server listens on a dynamic namespace and can start emitting on a child namespace before a client connects. This causes clients to not trigger the event listeners on the matching dynamic namespace when they do eventually connect. We are looking for a solution without using the workaround motioned above. Any suggestions would be appreciated. |
I've added a note here; https://socket.io/docs/v4/namespaces/#dynamic-namespaces In your example, the connection handler is only called if there is no existing namespace that matches. But since the "dynamic-1" was already registered (by calling That being said, I'm open to suggestions on how we could improve this. |
We also hit this issue and lost a day trying to figure it out before I found this issue. It seems like the client or the server should be able to create a namespace in the dynamic namespace range and have it handled by the dynamic namespace handler. Can anyone think of a use case where the current behavior would be required? |
@thombohlk Does your workaround fix the issue in a cluster as well? |
@dknapp47 Yes, we are running multiple workers in our cluster. The workaround ensures that a child namespace on which a worker wants to broadcast (e.g. |
Well I would certainly make sense to register all middlewares / event handlers that were defined on the dynamic namespace level when .of() is called with a string and it matches a dynamic namespace, not only when the first connection is done. The current flow is confusing and unexpected. Especially in the multi instance (cluster) usecase where you want to emit event to a namespace even if there were no connections in your instance yet. We will use the workaround from @thombohlk to match that behavior for now. |
Our team is being affected by this unexpected behavior (middlewares and events not executed when having emitted an event to a dynamic namespace for which a socket has not connected yet). We do not think that this behavior should be the default. |
@dgg this should be fixed by 0d0a7a2, included in version A namespace whose name matches the regex of a parent namespace will now be added as a child of this namespace: const parentNamespace = io.of(/^\/dynamic-\d+$/);
parentNamespace.on("connection", (socket) => {
console.log(`connection on namespace ${socket.nsp.name}`);
}); And then somewhere else: io.of("/dynamic-101"); Could you please check? |
Namespaces that match the regex of a parent namespace will now be added as a child of this namespace: ```js const parentNamespace = io.of(/^\/dynamic-\d+$/); const childNamespace = io.of("/dynamic-101"); ``` Related: - socketio#4615 - socketio#4164 - socketio#4015 - socketio#3960
Namespaces that match the regex of a parent namespace will now be added as a child of this namespace: ```js const parentNamespace = io.of(/^\/dynamic-\d+$/); const childNamespace = io.of("/dynamic-101"); ``` Related: - socketio#4615 - socketio#4164 - socketio#4015 - socketio#3960
Describe the bug
Generic description
When a server emits an event on a custom namespace before any client has connected to that namespace, event listeners on a dynamic namespace that matches the custom namespace will not work. When a client connects to the custom namespace after an event has been emitted on it, the event listeners of the matching dynamic namespace will not trigger.
Our concrete use case
We have a setup where we have a node cluster with multiple workers. Each worker is both used to communicate with clients using socket.io websockets and to run long running jobs on the background and emit progress about these jobs. The setup uses the Redis adapter to let socket.io communicate between workers.
We setup the "connect" event listeners on the serverside with a dynamic namespace, lets say
/^\/dynamic-\d+$/
. Then, when a worker starts on a job it will start emitting on namespacedynamic-7
for instance.We have experienced that the event listeners on the dynamic namespace do not work anymore for a particular worker when that worker starts emitting on a matching custom namespace before any client connects to the worker with the same custom namespace.
So, this works:
/^\/dynamic-\d+$/
/dynamic-7
/dynamic-7
But this doesn't:
/^\/dynamic-\d+$/
/dynamic-7
/dynamic-7
To Reproduce
Be sure to start the server script before starting the client script.
Socket.IO server version:
4.3.2
Server
Socket.IO client version:
4.3.2
Client
Expected behavior
I would expect the server to be able to start emitting events on a custom namespace that matches a dynamic namespace, even if no client has yet connected to that namespace.
Platform:
Additional context
Note that for us the cluster setup caused the bug to arise, but it is not necessary as the reproduction example demonstrates.
Our current workaround is to execute
io._checkNamespace("/dynamic-1", {}, () => {})
before we execute the first emit. This ensures that the custom namespace is added to the dynamic namespace and the event listeners of the dynamic namespace are copied to the custom namespace.The text was updated successfully, but these errors were encountered: