2013/8/29 Forrest L Norvell <[email protected]>: > Hey Alvaro, > > I needed the exact behavior you describe, and for a while to was also > following an approach based on domains. Ultimately, I encountered a few > issues that made it too difficult for me to proceed. One was that I was > writing a module, not an app, and I needed the state I was setting up to > persist through arbitrary user code, and if others are using domains for > their intended purpose, it can be very difficult to guarantee that > domains-as-state will be available at some arbitrary point down the road. > Another issue, which was my personal breaking point, was that my module also > needs to be able to capture information about errors raised in user code > without altering how those errors are handled. The conflation of concerns > that resulted made for a lot of very complicated and fragile code, as well > as a more or less intractable thicket of edge cases. > > So instead I (with some important help from Tim Caswell) made what I'm > calling "continuation-local storage" (the name's verbose, which is a(n > over)reaction to how confusing "domain" is as a name for what the module > does). The API is described at > https://npmjs.org/package/continuation-local-storage, and a glue module that > monkeypatches support for it into 0.10 and 0.8 is at > https://npmjs.org/package/continuation-local-storage-glue. It supports > multiple independent applications of CLS via namespaces, and doesn't > interfere with domains at all. > > Because the glue has to monkeypatch everything that crosses asynchronous > boundaries in node, it's not as efficient as it could be, so there's been > some discussion between some of the Node developers about adding support in > 0.12 or 1.0 to provide an asynchronous listener that would allow both > domains and other applications, like CLS, to do what they need to do. Trevor > Norris has been working on this for the last couple weeks, and his latest > sketch of an API is http://gist.github.com/trevnorris/6372405. It's pretty > simple, can be made fast (no closure creation!), and has the cool side > effect of disentangling domains from the core of Node. > > continuation-local-storage-glue isn't quite finished yet (which is why I > haven't announced it), but it is in use in real code right now, and so far > all indications are that it does exactly what it's supposed to without > interfering with domains. Check it out and tell me what you think. > > Forrest
Hi Forrest, Thanks for your feedback, I must say that it's the first time someone tells me that tried using domains and found actual problems. CLS looks really interesting! Now I understand a little better what Isaac meant in the quite popular mail "The Future of Programming in Node.js". I failed to see how could domains be implemented in userland, at least with an unpatched version of Node, and it seems that it's just not possible. My question now is, wouldn't it be better to have a standard (as in "inside of node") way of doing this? There are some modules that I think would make sense to have in node, like this one or logging. Anyway. I think that we both try to achieve the same but have different requirements. The restrictions that you mention led you to write CLS don't apply to Kolba, I think. Maybe I'm missing something? Cheers! > On Thursday, August 29, 2013, Alvaro Mouriño wrote: >> >> Hi all, >> >> Thanks for your answers. I'll try to address all your questions: >> >> * What are the advantages of using domains? >> The killer feature, for me, was that all the new events created inside >> a domain get propagated only inside such domain. This allowed me to >> use events without worrying about polluting other requests. >> >> Having the request globally accessible is a (nice) side effect, even >> if that were not possible, I think domains are still worth using. >> >> * What's so bad with passing the request object around? >> Nothing, actually. What I do find wrong is passing it "just in case", >> adding one more parameter to every call because some method deep in >> the call chain may need to make use of it. This is typically the case >> with template helpers. >> >> Is not unusual to have a helper function somewhere that checks, for >> example, if the user is logged in. For this specific cases I find it >> very useful to have the request always available. >> >> Global variables have very well defined dangers [0], which can be >> controlled by: >> 1. Making use of it in as few places as possible. >> 2. Treating it as read-only. >> >> If this 2 rules are followed, there are some cases where they are just >> the cleanest solution. Think about the typical use of environment >> variables, which is to tell a software which configuration file to >> use. It's very handy, gives us a mechanism to modify a software's >> behavior without having access to its code. This works because that >> variable is read in only one place and is never modified. You have to >> be very strict about it. >> >> I even advice against globals in the documentation [1]. >> >> Juraj, the `this.request` approach is a good idea, would be useful to >> get rid of the parameter injection which I'm not very happy with. But >> it doesn't make the request globally accessible, right? As I said, I >> like the idea of having both options and trust that the user will use >> them responsibly. >> >> Kevin, if I understood correctly, you say that variables defined >> globally may leak outside the domain? I guess that it's already a >> problem with the fact that Node runs in a single thread. Global >> variables are global to every request, and I don't attempt to "fix" it >> with domains, only to provide global access to the request. >> >> Cheers! >> >> [0] http://c2.com/cgi/wiki?GlobalVariablesAreBad >> [1] https://github.com/tooxie/kolba#cons >> >> >> 2013/8/29 Kevin Swiber <[email protected]>: >> > On Thu, Aug 29, 2013 at 5:20 AM, Alvaro Mouriño <[email protected]> >> > wrote: >> >> >> >> Hi list, >> >> >> >> I started working with NodeJS quite recently, even if at first I was a >> >> little skeptical about it, after using it intensively for the last >> >> couple of months I realized it's an amazing piece of technology. The >> >> only thing that I miss from other frameworks is the concept of >> >> thread-locals. >> >> >> >> After some time researching on this, a friend told me that this >> >> behavior could be achieved using domains [0]. I built a small >> >> framework, Kolba [1], as a proof of concept of how I see this being >> >> implemented. I also wrote an article explaining this idea and >> >> presenting some questions that I have. >> >> >> >> The main question that I want to ask here is: What am I missing? Why >> >> is this undocumented? Are there any edge cases that I don't see, which >> >> make this idea non-viable? >> >> >> >> Actually, the biggest problem I'm facing with the use of domain is the >> >> suppression of exceptions. I may be using it wrong probably, which >> >> leads to errors being silenced, but nothing regarding the emulation of >> >> thread-locals. >> > >> > >> > Hey Alvaro, >> > >> > I think the big difference here is that variables are not necessarily >> > domain-local and can be referenced outside a domain or even in multiple >> > domains. This means that bad state can leak and cause an exception >> > domino >> > effect. In the Web server scenario, this could mean killing all >> > currently >> > executing requests in a cluster. >> > >> > You could certainly structure your application/module to mimic >> > "request-local" behavior to an extent, but this isn't a pattern or >> > guarantee >> > Node is pushing out of the box with domains. >> > >> > The big benefit of domains is capturing execution state on uncaught >> > exceptions, potentially allowing for a graceful shutdown and more >> > helpful >> > logging. That's how I'm using domains in Pipeworks[1] (an execution >> > pipeline tool) and more recently, Argo[2] (an HTTP reverse proxy and >> > origin >> > server for APIs). So far, so good. >> > >> > In short, the idea of "request-local" variables isn't non-viable, just >> > nearly impossible to guarantee; you have to rely on module dependents >> > using >> > the right patterns for your framework. >> > >> > [1] https://github.com/kevinswiber/pipeworks#pipelinefaultcallback >> > [2] https://github.com/argo/argo/blob/master/example/cluster.js#L10-L22 >> > >> > -- >> > Kevin Swiber >> > Projects: https://github.com/kevinswiber >> > Twitter: @kevinswiber >> > >> > -- >> > -- >> > Job Board: http://jobs.nodejs.org/ >> > Posting guidelines: >> > https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines >> > You received this message because you are subscribed to the Google >> > Groups "nodejs" group. >> > To post to this group, send email to [email protected] >> > To unsubscribe from this group, send email to >> > [email protected] >> > For more options, visit this group at >> > http://groups.google.com/group/nodejs?hl=en?hl=en >> > >> > --- >> > You received this message because you are subscribed to the Google >> > Groups >> > "nodejs" group. >> > To unsubscribe from this group and stop receiving emails from it, send >> > an >> > email to [email protected]. >> > For more options, visit https://groups.google.com/groups/opt_out. >> >> >> >> -- >> Alvaro Mouriño >> >> -- >> -- >> Job Board: http://jobs.nodejs.org/ >> Posting guidelines: >> https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines >> You received this message because you are subscribed to the Google >> Groups "nodejs" group. >> To post to this group, send email to [email protected] >> To unsubscribe from this group, send email to >> [email protected] >> For more options, visit this group at >> http://groups.google.com/group/nodejs?hl=en?hl=en >> >> --- >> You received this message because you are subscribed to the Google Groups >> "nodejs" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to [email protected]. >> For more options, visit https://groups.google.com/groups/opt_out. > > -- > -- > Job Board: http://jobs.nodejs.org/ > Posting guidelines: > https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines > You received this message because you are subscribed to the Google > Groups "nodejs" group. > To post to this group, send email to [email protected] > To unsubscribe from this group, send email to > [email protected] > For more options, visit this group at > http://groups.google.com/group/nodejs?hl=en?hl=en > > --- > You received this message because you are subscribed to the Google Groups > "nodejs" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > For more options, visit https://groups.google.com/groups/opt_out. -- Alvaro Mouriño -- -- Job Board: http://jobs.nodejs.org/ Posting guidelines: https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines You received this message because you are subscribed to the Google Groups "nodejs" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/nodejs?hl=en?hl=en --- You received this message because you are subscribed to the Google Groups "nodejs" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/groups/opt_out.
