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

Add cleanupEmptyChildNamespaces server option #4602

Conversation

stevebaum23
Copy link
Contributor

  • When a socket disconnects from a child namespace (those created by a ParentNamespace), if this option is enabled and there are no other sockets connected, it will call nsp.adapter.close() and remove the namespace.
  • The namespace can be connected to later (it will be recreated)
  • Added some tests to cover the new code changes

The kind of change this PR does introduce

  • a bug fix
  • a new feature
  • an update to the documentation
  • a code change that improves performance
  • other

Current behavior

Currently, child namespaces (those created by a ParentNamespace, maybe dynamic namespace is the correct term?) exist forever while the server is running. This can cause issues with certain adapters (like redis) where it continues to subscribe and never unsubscribes, as pointed out in this issue.

New behavior

This PR adds a new server option, cleanupEmptyChildNamespaces. With this option enabled, when a client socket disconnects, if there are no other sockets connected to the namespace, the following with occur:

  • Call nsp.adapter.close()
  • Remove the namespace from the servers internal namespace list (_nsps)
  • Remove the namespace from it's parent list (ParentNamespace.children)

Calling adapter.close() will allow the adapters to clean up any subscriptions.

Removing the namespace from _nsps is necessary, otherwise the adapters won't re-subscribe when the namespace is connected to again.

Removing the namespace from the ParentNamespace.children is to prevent memory leaks, since the old namespace is no longer used.

Other information (e.g. related issues)

One thing I'm unsure of is how this will affect the other adapters. I only use the redis adapter, which doesn't implement close yet (I will be creating a new PR to implement it). I don't know if calling close on the other adapters would have some bad side effects.

- When a socket disconnects from a child namespace (those created by a ParentNamespace), if this option is enabled and there are no other sockets connected, it will call nsp.adapter.close() and remove the namespace.
- The namespace can be connected to later (it will be recreated)
- Added some tests to cover the new code changes
darrachequesne pushed a commit that referenced this pull request Jan 23, 2023
This commit adds a new option, "cleanupEmptyChildNamespaces". With this
option enabled (disabled by default), when a socket disconnects from a
dynamic namespace and if there are no other sockets connected to it
then the namespace will be cleaned up and its adapter will be closed.

Note: the namespace can be connected to later (it will be recreated)

Related: socketio/socket.io-redis-adapter#480
@darrachequesne
Copy link
Member

Merged as 5d9220b. Thanks a lot 👍

@stevebaum23 stevebaum23 deleted the add-cleanupEmtpyChildNamespaces-option branch February 1, 2023 21:36
haneenmahd pushed a commit to haneenmahd/socket.io that referenced this pull request Apr 15, 2023
This commit adds a new option, "cleanupEmptyChildNamespaces". With this
option enabled (disabled by default), when a socket disconnects from a
dynamic namespace and if there are no other sockets connected to it
then the namespace will be cleaned up and its adapter will be closed.

Note: the namespace can be connected to later (it will be recreated)

Related: socketio/socket.io-redis-adapter#480
dzad pushed a commit to dzad/socket.io that referenced this pull request May 29, 2023
This commit adds a new option, "cleanupEmptyChildNamespaces". With this
option enabled (disabled by default), when a socket disconnects from a
dynamic namespace and if there are no other sockets connected to it
then the namespace will be cleaned up and its adapter will be closed.

Note: the namespace can be connected to later (it will be recreated)

Related: socketio/socket.io-redis-adapter#480
@carera
Copy link
Contributor

carera commented Jul 18, 2023

Hello @stevebaum23 and @darrachequesne
We greatly benefited from your leak fix in this PR!

We have stumbled upon a similar issue, when using Redis adapter, tho not sure how should we go about fixing it. It appears that adapter cleanup isn't called when a socket.io middleware throws exception:

I created a separate bug for this: #4772

I attempted a PR here but that does not seem to be the correct approach - we should only clean up when there are no more sockets

Would you be able to help?

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

Successfully merging this pull request may close these issues.

3 participants