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