Cool - thanks!

This definitely could be better documented.  It's a pretty easy trap to 
fall into.

Also, your solution still depends on process.domain which isn't mentioned 
officially (ie. at http://nodejs.org/api/process.html ).


On Monday, 12 November 2012 18:55:33 UTC, Forrest L Norvell wrote:
>
> On Monday, November 12, 2012 at 7:25 AM, pie_lard wrote:
>
> Hi,
>
> I'm trying to use domains to catch application-level errors in my server. 
>  I'm using express, connect, node-mysql and generic-pool.
>
> The node docs give an example at 
> http://nodejs.org/api/domain.html#domain_explicit_binding which shows how 
> to create a new domain per incoming request - ie. create the domain early 
> on during the servicing of the request.  That way any uncaught errors can 
> be handled by a domain that also has access to the correct response object 
> and can thus send an error back to the client browser (which wouldn't be 
> possible with a single domain handling everything).
>
> This approach seems to work until I introduce my pool of database 
> connections.  I think the problem is that it is possible for code that's 
> servicing a request to acquire a database connection that was created 
> earlier - perhaps while a different request was being serviced or during 
> server initialisation.
>
> This is exactly correct. 
>
> If that happens then when a query is executed and executes a callback the 
> callback will be running under the earlier domain.  In other words, 
> executing a query effectively moves the execution of all subsequent code to 
> a different domain.
>
> This will only be true if a domain is active at the time the connection 
> was created, and remains active when your query is run. Otherwise, the 
> underlying EventEmitter won't be on a domain. 
>
>
> Obviously this can cause problems that are quite hard to diagnose - eg. 
> sometimes an error generated for a particular session might be sent to a 
> different session.  Such errors will be dependent on precise timing issues 
> and can be hard to recreate etc.
>
> I think I can solve the problem by doing something like this whenever I 
> need to run a query:
>
>       priorDomain = process.domain;
>       connection.query(sql, params, function(err, rows, cols) {
>         // Jump back under the original domain before continuing
>         return priorDomain.run(function() {
>            ...process results...
>         });
>       });
>
> But that doesn't seem right because I'm using process.domain which as far 
> as I can tell is undocumented.  It also just doesn't feel like the correct 
> solution ;)
>
> Have I missed some obvious solution to this?  Or just misunderstood what's 
> happening?
>
> Nope, you've stumbled into a (known, but not particularly well-documented) 
> edge case with domains, which is that EventEmitters created before the 
> domain don't run user-provided callbacks in the domain. The ideal solution 
> is for the authors of the relevant modules (generic-pool, node-mysql, 
> node-mongodb-native, node-redis, etc) to add support for domains to their 
> modules. You can partially work around this by rewriting your code like 
> this:
>
> priorDomain = process.domain;
> var handler = function (err, rows, cols) {
>   // process results
> };
>
> connection.query(sql, params, priorDomain.bind(handler));
>
>
> (assuming that priorDomain exists -- if you're running an entire Express 
> handler within a domain using domain.run(), you should use the domain you 
> created for that to bind your callback to the domain.
>
> F
>

-- 
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

Reply via email to