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