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
