-
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
Support dynamic namespaces #1921
Conversation
This approach looks more promising over other dynamic namespace approaches I have seen here. |
+1, seems great and simple. |
@@ -43,6 +43,7 @@ function Server(srv, opts){ | |||
} | |||
opts = opts || {}; | |||
this.nsps = {}; | |||
this.fns = []; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
needs a more descriptive name
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to npsValidators
. Let me know if that works.
This helps us for the cloud project because we need to be able to support arbitrary namespace connections there. |
👍 This approach looks great to me too. |
I like it. 👍 |
@defunctzombie - I'm glad you like this. I'm happy to cleanup anything stylistically as well. If there is a style guide or examples to look at let me know. |
I like the simple approach too. But a question: with this approach, is there a clean way to implement namespace timeouts or cleanup when there are no client connected to a namespace anymore? For applications (like mine) that support a large number of mostly-unused namespaces, we need a way to avoid leaking them when they go unused. |
@dylanlingelbach mostly renaming that array of functions. Another stylistic thing I noticed was just return early from if blocks instead of if..else nested sections. Otherwise looks good. Do you have thoughts around what @davidbau said on cleaning up namespaces when clients disconnect? If we can't tap into a disconnect event, then we could have a reaper timer that just cleans up. Does anyone see a downside to automatically cleaning up unused namespaces? |
@defunctzombie - ok, cool, I'll take a stab at cleaning up the stylistic stuff today. The downsides I see to automatic cleanup are more complex code and less flexibility around when cleanups happen. What if one wants to keep currently unused namespaces around and another doesn't? How about The approach I outline above definitely puts more burden on the application to clean up but I think the code would be simpler and more flexible. If the vast majority of applications want automatic cleanup then I think it makes sense to have a more automatic cleanup mechanism. Thoughts? I'm happy to code this up if people like the approach. Also happy to code it up if people want to take a deeper look. |
I was working on cleaning up/adding some tests and may have hit an issue with this approach. On a dynamic namespace connection the Additionally the middleware for the namespace doesn't run because the server had no way to add it. I'm not sure if this will be an issue in practice. My feeling is the Or is it ok that the |
@dylanlingelbach What do you mean by client being present? |
I mean client connecting to a dynamic namespace prior to the server calling Here is the sequence I am worried about: 1 - Client tries to connect to a namespace the server hasn't created yet:
2 - The server allows the dynamic namespace which will create the
Does that better explain the scenario I'm thinking about? I'm not sure if the middleware not being called for the existing connection and the |
@dylanlingelbach can you squash into a single commit and rebase on master. It seems some things have changed on master that cause conflicts. |
d38bd91
to
9a13cff
Compare
@defunctzombie - yep, squashed and rebased. |
c799eb2
to
066863e
Compare
@defunctzombie - anything else you need me to do on this? No rush, just making sure you weren't waiting on me |
I think @rauchg needs to have a review of this feature. To me it looks good. |
Any word on this PR? |
I'm waiting for a code review - I was planning on rebasing after the review. |
@dylanlingelbach Have you created any documentation for this feature? If so can you please direct me to it. Thanks! |
@CxRes - I have not other than comments in the code. I wasn't sure where to add the documentation. Happy to add it wherever needed. |
@dylanlingelbach: I wouldn't know the best place to add, since I am not sure of how the documentation is being handled. Can anybody from the socket.io team please advise? My best guess is to make a PR to readme.me file at the root of the project and perhaps a PR on the socket.io-website repo. Sorry for the trouble, but it is feature that appears to fit my use-case and so am itching to test it out. |
any progress on this? prs seem slow to merge at the minute, one issue im having is connecting namespaces via an outside source (php laravel) the socket.io server just listens to redis events and emits them on the event.namespace, so the server has no knowledge of the namespace until it emits, and this causes issues if i dont define them upfront. can we get this added anytime soon? |
@leemason I am at the moment maintaining a fork with @dylanlingelbach code which is rebased on to the most recent master at http://github.com/cxres/socket.io#dynamic-namespaces. The only documentation are the tests, though it is relatively straightforward to use. |
@leemason Here is a gist with example usage |
@CxRes thanks for sending me that, ive ended up building my own package ontop of engine.io instead as i was spending more time reverse engineering the features than doing what i needed, cheers anyway. |
So..... Am I right in thinking we still don't have this ability in master ? |
@z639 I do not think socket.io folks care... |
Annoying... very annoying. |
@z639 thanks for bringing that to my attention, I'll try to take a look at the pull request and make the necessary edits by the end of the week. |
@darrachequesne Thanks for looking into this. I'm actually still confused as to why this wasn't the default behaviour right from the beginning. I mean, if the client is sending a valid namespace and nothing is hard-coded at the server, then why wouldn't that namespace be used ? There's likely a valid reason and that would also explain why this PR was ignored for so long. Any feedback would be great. |
Merged as #3187. |
Thanks for the hard work! |
@darrachequesne I see that you have rebased #1921. I had made a few changes in a fork because there were a few minor issues with the implementation as I had discussed with @dylanlingelbach above. Could you please look into it and if it appears OK, I could PR those changes as well.... There are essentially 2 issues that I address in the fork:
|
@CxRes yes, could you please open a pull request with those changes? A few questions:
server.on('newNamespace', (name) => {
server.of(name).on('connect', /* ... */);
}); |
@darrachequesne please give me a bit of time, I get back to this when I have a bit of time on hand. To answer your questions:
The
Since the name is already available above this seems a bit superfluous. I am not a fan of having a
Something like:
What we are doing now is:
This is incidentally why I was especially frustrated with the otherwise good folks here - v2.0 bump would have been the best time to rethink any API changes which could make this feature feel a natural part of socket.io (and the matter was raised at v1.5). |
On first thought, |
Would the following make sense? let dynamicNsp = server.of((nsp, conn, next) => {
next(null, /^\/dynamic-\d+$/.test(nsp));
}).on('connect', (socket) => {
let nsp = this;
nsp.emit('hello');
});
dynamicNsp
.use(middleware)
.emit('hello')
// ...
Then So |
@darrachequesne Thanks for your work. I had a look at your code (which is quite different from the 1.x code). In a sense it is really short and sweet so I am reluctant to do suggest too much change (and I would need to test it myself at some point in a real program). Having said that there are a few things I want you to consider: You need to be able to return why a namespace failed to the client. It is not clear to me if this happens... especially relevant in your test which only checks for the regex version. If this fails the you need to able to return a message that goes something like "failed to connect: does not match a namespace pattern for this server". Really rethink if you need a Finally make sure that disconnect on a namespace is isolated to that - it does not disconnect everything. This was a bug I had to fix after realizing it the hard way i.e. in a failing implementation. |
@CxRes thanks for your response!
What should happen when there are several dynamic namespaces? Example: io.of(/^\/dynamic-\d+$/).on('connect', /* ... */);
io.of(/^\/another-\w+$/).on('connect', /* ... */);
io.of((nsp, query, next) => next(new Error('not implemented yet'))).on('connect', /* ... */); In that case, which error message should we send to the client?
In my example above, the io.of(/^\/dynamic-\d+$/).on('connect', (socket) => {
// socket.nsp.name = '/_0'
});
io.on('newNamespace', (nsp) => {
nsp.on('connect', (socket) => {
// socket.nsp.name = '/dynamic-101'
});
}); So in that case I think the
So that we have: io.of(/^\/dynamic-\d+$/).on('connect', (socket) => {
// socket.nsp.name = '/dynamic-101'
}); But in that case, what should Hope I'm clear enough! Edit: I updated #3195, could you please take a look? |
@darrachequesne I am beginning to understand where our thought processes differ. You come from a perspective of socket.io coder and I am coming from a user who is not even well versed in the API but desire something to work in a certain way. It would actually have been useful to thrash it out on a board over coffee rather than such an async verbose medium. My understanding was that the user would define the I suspect your objection will be that in static case we do not define This also dovetails into the |
Between all the different github issues, it is really hard to figure out what has been merged/implemented and what hasn't, in terms of dynamic namespaces. The documentation doesn't mention any of the above solutions at all. I've spent some time implementing what I thought was released in 2.1.0 ( It'd be great if someone could update the documentation with what the current state and functionality of dynamic namespaces is. Edit: for anyone else finding this, looks like the regex approach works and is implemented: io
.of(/^\/[a-z0-9-.]+$/)
.on('connect', socket => {
console.log('DYNAMIC:', socket.nsp.name);
}); |
I am not using socket.io anymore, in part because the change that was landed in 2.x was not consistent with this proposal. In particular, the maintainers refused to implement any way for clients to learn the reason for rejection of a namespace (and the code base had changed significantly between 1.x and 2.x for non-maintainers to PR a fix without considerable study)! To see what has been actually implemented in master see PR #3195! |
What alternative are you using now, if I may ask?
…On Wed, 16 Sep 2020, 22:47 CxRes, ***@***.***> wrote:
I am not using socket.io anymore, in part because the change that was
landed in 2.x was not consistent with this proposal. In particular, the
maintainers refused to implement any way for clients to learn the reason
for rejection of a namespace (and the code base had changed significantly
between 1.x and 2.x for non-maintainers to PR a fix without considerable
study)!
To see what has been actually implemented in master see PR #3195
<#3195>!
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#1921 (comment)>,
or unsubscribe
</~https://github.com/notifications/unsubscribe-auth/AADXYQTCIRDIFK4OM5ZC74DSGCJUDANCNFSM4AZKYABA>
.
|
I have switched to ordinary websockets for now (its not ideal though). I wish I could be of more help! |
@adamreisnz I agree, there could be more examples about dynamic namespaces in the documentation. Dynamic namespaces are mentioned in the Server API and in the Namespaces page though. |
Yes, I noticed it on the Server API page eventually, but missed it on the Namespaces pages. It only has a brief mention on the namespaces page, but I reckon it probably deserves its own section under Namespaces. |
This is another attempt to fix #1854. It is much more limited in its approach (no automatic disconnects and no host support - as in #1865).
I'm new to the code base so not sure if this is the right approach - open to feedback on how I'm doing this. The questions I have with my approach:
useNamespace
for adding the middleware? Name feels odd but couldn't think of anything better.Thanks to @davidbau for #1865 which got me going in the right direction.