Account Options

  1. Sign in
The old Google Groups will be going away soon, but your browser is incompatible with the new version.
Google Groups Home
« Groups Home
Domains and connection pools
There are currently too many topics in this group that display first. To make this topic appear first, remove this option from another topic.
There was an error processing your request. Please try again.
flag
  Messages 1 - 25 of 28 - Collapse all  -  Translate all to Translated (View all originals)   Newer >
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
pie_lard  
View profile  
 More options Nov 12 2012, 10:25 am
From: pie_lard <pie_l...@yahoo.com>
Date: Mon, 12 Nov 2012 07:25:29 -0800 (PST)
Local: Mon, Nov 12 2012 10:25 am
Subject: Domains and connection pools

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

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?

Any thoughts very welcome,

Thanks.


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Forrest L Norvell  
View profile  
 More options Nov 12 2012, 1:55 pm
From: Forrest L Norvell <forr...@newrelic.com>
Date: Mon, 12 Nov 2012 10:55:09 -0800
Local: Mon, Nov 12 2012 1:55 pm
Subject: Re: [nodejs] Domains and connection pools

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.

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


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
pie_lard  
View profile  
 More options Nov 12 2012, 6:36 pm
From: pie_lard <pie_l...@yahoo.com>
Date: Mon, 12 Nov 2012 15:36:11 -0800 (PST)
Local: Mon, Nov 12 2012 6:36 pm
Subject: Re: [nodejs] Domains and connection pools

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


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Forrest L Norvell  
View profile  
 More options Nov 12 2012, 6:56 pm
From: Forrest L Norvell <forr...@newrelic.com>
Date: Mon, 12 Nov 2012 15:56:25 -0800
Local: Mon, Nov 12 2012 6:56 pm
Subject: Re: [nodejs] Domains and connection pools

On Monday, November 12, 2012 at 3:36 PM, pie_lard wrote:
> 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 ).

For that, I was just following your lead. I think the intent is that process.domain is meant to be used by library writers who want to make use of domains without directly depending on node 0.8+. There's also domain.active, for code that's built to be domain-aware from the get-go.

However, my assumption is that the typical domain pattern is going to look a lot more like:

var domain = require('domain');
// setup...

app.get('/thinger/:doer', function (req, res) {
  var d = domain.create();
  d.on('error', function (error) { /* oh no */ });
  d.run(function () {
    // do a buncha stuff
    db.query("SELECT * FROM foo WHERE ?", params, d.bind(function (err, rows, cols) {
      // handle
    });
  })

}

or, more succinctly (using domain.intercept, which is documented, but not with any particularly convincing motivation):

var domain = require('domain');
// setup...

app.get('/thinger/:doer', function (req, res) {
  var d = domain.create();
  d.on('error', function (error) { /* oh no */ });
  d.run(function () {
    // do a buncha stuff
    db.query("SELECT * FROM foo WHERE ?", params, d.intercept(function (rows, cols) {
      // handle
    });
  })

}

I gave a little talk on domains last week, and my slides are here: http://othiym23.github.com/domainion/

It's my first cut at this material and tries to put all this in context, and might help you figure out what's going on a little better.

F

Forrest L Norvell
Node.js agent engineer
| E forr...@newrelic.com (mailto:forr...@newrelic.com) | C (415) 823‑6356 | T @othiym23 (http://twitter.com/othiym23) | G github.com/othiym23 (https://github.com/othiym23) | W newrelic.com (http://newrelic.com/)
( ( •))  New Relic  


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
pie_lard  
View profile  
 More options Nov 14 2012, 2:29 pm
From: pie_lard <pie_l...@yahoo.com>
Date: Wed, 14 Nov 2012 11:29:39 -0800 (PST)
Local: Wed, Nov 14 2012 2:29 pm
Subject: Re: [nodejs] Domains and connection pools

Thanks - I see your slides already mentioned this very pitfall ;)

I think the problem with the examples you've posted there is that you are
creating a domain for every query() call and also having to remember to
wrap the callback in bind() or intercept().  That's too much of a burden
for every call - particularly when the official node docs imply that one
simply has to create a domain during the early stage of an incoming request
and from then on exceptions will be caught properly.

I'm not a node expert but I can't help but wonder if domains would be
easier to use if they simply stayed in place across all callbacks and
didn't have this notion of 'owning' EventEmitters.  That way all you would
need to do is install a domain and never have to worry about whether your
pooled resources are going to dump you into a different domain at some
point.

Maybe this would only work if node were to maintain a stack of domains -
I'm not sure of the implications of that.

I realise I'm probably missing something important here ;)  Either what I'm
suggesting wouldn't work or couldn't be easily implemented.  I see there's
another discussion going on on this list about node modules that seem to be
alternatives to domains (or are they built on domains somehow?),


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Forrest L Norvell  
View profile  
 More options Nov 14 2012, 2:46 pm
From: Forrest L Norvell <forr...@newrelic.com>
Date: Wed, 14 Nov 2012 11:46:12 -0800
Local: Wed, Nov 14 2012 2:46 pm
Subject: Re: [nodejs] Domains and connection pools

On Wednesday, November 14, 2012 at 11:29 AM, pie_lard wrote:
> I think the problem with the examples you've posted there is that you are creating a domain for every query() call and also having to remember to wrap the callback in bind() or intercept().  That's too much of a burden for every call - particularly when the official node docs imply that one simply has to create a domain during the early stage of an incoming request and from then on exceptions will be caught properly.

The danger of using a slide deck as a reference is that the examples are contrived to give me something simple to live-code to in a presentation. If you're willing to make liberal use of domain.bind(), there's no reason why you can't just have one domain for a whole class of requests and add long-lived connections to the domain directly (although then it becomes more important to analyze the lifecycle of the domains and ensure that you're disposing of them properly when they're no longer needed).

It's worth mentioning that domains are simple objects and are pretty cheap to create -- mostly just the cost of creating a new EventEmitter and adding a couple closures to it. Unless your code is super-hot, it shouldn't add very much overhead to run a specific request in a domain.

> I'm not a node expert but I can't help but wonder if domains would be easier to use if they simply stayed in place across all callbacks and didn't have this notion of 'owning' EventEmitters.  That way all you would need to do is install a domain and never have to worry about whether your pooled resources are going to dump you into a different domain at some point.

Essentially that's what uncaughtException does; the added value of domains is that it adds context to errors and lets you perform cleanup and recovery in a manner similar to what you'd get with exceptions in the synchronous case.

> Maybe this would only work if node were to maintain a stack of domains - I'm not sure of the implications of that.

Domains can be nested -- only the current innermost domain will receive error events. This is handled by a stack internally to the domain code. You could get multiple listeners on a domain by adding additional listeners, although you'd have to clean them up at the end of the scope manually. Probably better just to create a new domain.

> I realise I'm probably missing something important here ;)  Either what I'm suggesting wouldn't work or couldn't be easily implemented.  I see there's another discussion going on on this list about node modules that seem to be alternatives to domains (or are they built on domains somehow?),

I'm aware of very few third-party modules taking advantage of domains so far. If anybody else knows of any, it would be awesome to hear about it.

F


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
pie_lard  
View profile  
 More options Nov 14 2012, 3:11 pm
From: pie_lard <pie_l...@yahoo.com>
Date: Wed, 14 Nov 2012 12:11:03 -0800 (PST)
Local: Wed, Nov 14 2012 3:11 pm
Subject: Re: [nodejs] Domains and connection pools

That wouldn't work in the case of pooled connections (or any pooled
resources that outlive requests) because you'd just have to add the
connection to the domain as soon as you require it (and remove it when
you've finished).  In which case you'd be better off if domains simply
could be installed and then 'followed' every callback from that point
onwards.  No need for your code to ensure it hasn't switched domains.

> It's worth mentioning that domains are simple objects and are pretty cheap
> to create -- mostly just the cost of creating a new EventEmitter and adding
> a couple closures to it. Unless your code is super-hot, it shouldn't add
> very much overhead to run a specific request in a domain.

Yes - I'm not questioning the performance of domains at all.

> I'm not a node expert but I can't help but wonder if domains would be
> easier to use if they simply stayed in place across all callbacks and
> didn't have this notion of 'owning' EventEmitters.  That way all you would
> need to do is install a domain and never have to worry about whether your
> pooled resources are going to dump you into a different domain at some
> point.

> Essentially that's what uncaughtException does; the added value of domains
> is that it adds context to errors and lets you perform cleanup and recovery
> in a manner similar to what you'd get with exceptions in the synchronous
> case.

I agree that domains are needed precisely to maintain the context (eg. I
can't send an error to a client if I've lost track of the response object -
which I would do with simple uncaughtExceptions).

> Maybe this would only work if node were to maintain a stack of domains -
> I'm not sure of the implications of that.

> Domains can be nested -- only the current innermost domain will receive
> error events. This is handled by a stack internally to the domain code.
> You could get multiple listeners on a domain by adding additional
> listeners, although you'd have to clean them up at the end of the scope
> manually. Probably better just to create a new domain.

Yes - I saw that in the docs.  I suppose what I'm asking amounts to: would
it matter if domains simply didn't keep track of EventEmitters - what would
be the implications? I think that might make nesting simpler (and could
possibly happen automatically whereas it doesn't at the moment to prevent
resource leaks).

> I realise I'm probably missing something important here ;)  Either what
> I'm suggesting wouldn't work or couldn't be easily implemented.  I see
> there's another discussion going on on this list about node modules that
> seem to be alternatives to domains (or are they built on domains somehow?),

> I'm aware of very few third-party modules taking advantage of domains so
> far. If anybody else knows of any, it would be awesome to hear about it.

I assume that any external library built on top of uncaughtExceptions won't
be able to track all callbacks without wrapping a lot of the standard
library functions or something like that.  I mean, domains are the best
solution because they are built into node and can thus do things that an
external module can't (easily anyway).

> F

Finally - I think perhaps the solution to my problem might be to change my
connection pool code so that the create() function creates the resource and
then checks whether a domain is installed.  If one is installed then it
should immediately remove the new resource from the domain.  From then on
the resource will belong to no domain and any errors will be caught by
whatever domain is installed at the time.  Again, though, it feels like I'm
writing code to make domains behave in a way that would be sensible as a
default.

 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Forrest L Norvell  
View profile  
 More options Nov 14 2012, 4:08 pm
From: Forrest L Norvell <forr...@newrelic.com>
Date: Wed, 14 Nov 2012 13:07:56 -0800
Local: Wed, Nov 14 2012 4:07 pm
Subject: Re: [nodejs] Domains and connection pools

On Wednesday, November 14, 2012 at 12:11 PM, pie_lard wrote:
> On Wednesday, 14 November 2012 19:46:28 UTC, Forrest L Norvell wrote:
> > If you're willing to make liberal use of domain.bind(), there's no reason why you can't just have one domain for a whole class of requests and add long-lived connections to the domain directly (although then it becomes more important to analyze the lifecycle of the domains and ensure that you're disposing of them properly when they're no longer needed).

> That wouldn't work in the case of pooled connections (or any pooled resources that outlive requests) because you'd just have to add the connection to the domain as soon as you require it (and remove it when you've finished).  In which case you'd be better off if domains simply could be installed and then 'followed' every callback from that point onwards.  No need for your code to ensure it hasn't switched domains.

I think I mentioned this already upthread, but the solution is to add support for domains to the modules that handle connection pools (here's my first stab at this, for node-redis: https://github.com/mranney/node_redis/pull/310). When the drivers are connection-aware, they work more or less exactly as you describe. When the API is more mature, app developers shouldn't have to even know about the implementation details of domains to use them.

> > It's worth mentioning that domains are simple objects and are pretty cheap to create -- mostly just the cost of creating a new EventEmitter and adding a couple closures to it. Unless your code is super-hot, it shouldn't add very much overhead to run a specific request in a domain.
> Yes - I'm not questioning the performance of domains at all.

In that case, it's not really a big deal to run each request in its own domain, is it?
> > > Maybe this would only work if node were to maintain a stack of domains - I'm not sure of the implications of that.

> > Domains can be nested -- only the current innermost domain will receive error events. This is handled by a stack internally to the domain code. You could get multiple listeners on a domain by adding additional listeners, although you'd have to clean them up at the end of the scope manually. Probably better just to create a new domain.

> Yes - I saw that in the docs.  I suppose what I'm asking amounts to: would it matter if domains simply didn't keep track of EventEmitters - what would be the implications? I think that might make nesting simpler (and could possibly happen automatically whereas it doesn't at the moment to prevent resource leaks).

The problem is that without wrapping up EventEmitters, the domains will get lost due to how async calling chains work. If you set the domain to be "global", you can never have overlapping domains, or in other words you lose request-specific context. Domains are basically trying to recreate synchronous call stacks by wrapping context around the asynchronous call graph, and to do that they need to wrap all of the various ways that Node sets up asynchronous execution (that's what the bulk of the domain-specific code does, in fact).
> > > I realise I'm probably missing something important here ;)  Either what I'm suggesting wouldn't work or couldn't be easily implemented.  I see there's another discussion going on on this list about node modules that seem to be alternatives to domains (or are they built on domains somehow?),

> > I'm aware of very few third-party modules taking advantage of domains so far. If anybody else knows of any, it would be awesome to hear about it.

> I assume that any external library built on top of uncaughtExceptions won't be able to track all callbacks without wrapping a lot of the standard library functions or something like that.  I mean, domains are the best solution because they are built into node and can thus do things that an external module can't (easily anyway).

You can do it, but it's hard and the results have performance implications. Look at longjohn or trycatch (which Adam Crabtree was just discussing on another thread). They use closures and shims that wrap around the same things that domains support from inside the Node core library. Domains have the potential to be a much simpler, cheaper solution to the more general problem of tying errors and requests together.

F


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
pie_lard  
View profile  
 More options Nov 14 2012, 4:35 pm
From: pie_lard <pie_l...@yahoo.com>
Date: Wed, 14 Nov 2012 13:35:49 -0800 (PST)
Local: Wed, Nov 14 2012 4:35 pm
Subject: Re: [nodejs] Domains and connection pools

I think we agree on most of these points.  I agree that I need to create a
domain per request - I wasn't suggesting an alternative to that.  I also
agree that domains seem to be attempting to recreate synchronous call-stack
exception handling.  Finally, I agree that domains are (must be?) a
superior solution to an external module for the reasons you mention.

My question boils down to this:

Suppose node were changed to remove the feature that lets domains track
EventEmitters.  So domain.add(), .remove() and .members would all be
removed.  The code that automatically adds new EventEmitters to the active
domain (if there is one) would also be deleted.  Finally, suppose .bind()
and .intercept() were also removed.

That would just leave domain.run() - plus the ability to create new domains
and possibly nest them.

Would that be enough to effectively recreate synchronous stack-based
exception handling?

My answer would be yes - and in fact it would remove my connection-pool
problem altogether without any need for the 3rd-party module authors to
change anything.

To put it another way; in what real-world circumstances would you need the
features I just removed?

Please understand I ask this as a bit of a node noob ;)  It's not a
criticism of domains - I would like someone to explain why I'm wrong about
this.


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Forrest L Norvell  
View profile  
 More options Nov 14 2012, 5:04 pm
From: Forrest L Norvell <forr...@newrelic.com>
Date: Wed, 14 Nov 2012 14:03:54 -0800
Local: Wed, Nov 14 2012 5:03 pm
Subject: Re: [nodejs] Domains and connection pools

Forrest L Norvell
Node.js agent engineer
| E forr...@newrelic.com (mailto:forr...@newrelic.com) | C (415) 823‑6356 | T @othiym23 (http://twitter.com/othiym23) | G github.com/othiym23 (https://github.com/othiym23) | W newrelic.com (http://newrelic.com/)
( ( •))  New Relic

On Wednesday, November 14, 2012 at 1:35 PM, pie_lard wrote:
> Suppose node were changed to remove the feature that lets domains track EventEmitters.  So domain.add(), .remove() and .members would all be removed.  The code that automatically adds new EventEmitters to the active domain (if there is one) would also be deleted.  Finally, suppose .bind() and .intercept() were also removed.

As an aside, you should only have to call domain.{add,remove} on a handle or an emitter yourself under very specific (and rare) conditions.
> That would just leave domain.run() - plus the ability to create new domains and possibly nest them.

> Would that be enough to effectively recreate synchronous stack-based exception handling?

No, and I'll explain why below.  
> My answer would be yes - and in fact it would remove my connection-pool problem altogether without any need for the 3rd-party module authors to change anything.

> To put it another way; in what real-world circumstances would you need the features I just removed?

> Please understand I ask this as a bit of a node noob ;)  It's not a criticism of domains - I would like someone to explain why I'm wrong about this.

The problem is it's impossible to know in advance whether a chunk of code is going to use EventEmitters or not, and without domain code there to wrap them, you'd lose the necessary state to tie a specific request to a specific domain. Consider the following (buggy / incomplete) Express handler:

app.get('/test', function (req, res) {
  var d = domain.create();
  d.on('error', function (error) { res.send(500, {"content-type":"text/plain"}, error.stack); });
  d.run(function () {
    fs.readFile(FILENAME, 'utf-8', function (err, contents) {
      // process.domain should be available here
      res.send(contents.replace(/:/gm, '/'));
    });
  });

});

The call to res.send is going to happen several passes through the event loop after the initial handler is called. It's entirely possible that in the time the file is read from disk, another several requests to that handler are going to have come in to the server. Without dealing with the EventEmitters, how will any errors emitted inside the fs.readFile callback be connected back to the enclosing domain?

F


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
pie_lard  
View profile  
 More options Nov 14 2012, 5:28 pm
From: pie_lard <pie_l...@yahoo.com>
Date: Wed, 14 Nov 2012 14:28:20 -0800 (PST)
Local: Wed, Nov 14 2012 5:28 pm
Subject: Re: [nodejs] Domains and connection pools

your example would in fact work (ie. that your domain handler would catch
an error thrown by the res.send() call).

The docs say:

Additionally, callbacks passed to lowlevel event loop requests (such as to
fs.open, or other callback-taking methods) will automatically be bound to
the active domain. If they throw, then the domain will catch the error.

Doesn't that imply that you've done all you need to do in the above code?
 That just by starting the chain of callbacks inside run() that the active
domain will persist through them?  And that as you're creating a new domain
per request the domains won't get confused - the correct res object will be
available when an error is thrown?

BTW: I didn't mean to imply that the domain code inside node could do this
without wrapping EventEmitters or something similar.  Just that (a) it
should do so behind-the-scenes and (b) the wrapping shouldn't take the form
of binding the EventEmitter to whatever domain happens to be active when
the emitter was created.

F


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Forrest L Norvell  
View profile  
 More options Nov 14 2012, 5:59 pm
From: Forrest L Norvell <forr...@newrelic.com>
Date: Wed, 14 Nov 2012 14:58:53 -0800
Local: Wed, Nov 14 2012 5:58 pm
Subject: Re: [nodejs] Domains and connection pools

I think we're very close to getting in sync here. Yes, with the domains code internally wrapping EventEmitters, the above is totally enough to trap errors on the correct domain. I was asking how that would work *without* EventEmitters being wrapped.

You shouldn't have to deal with any of the EventEmitter stuff. It should all be handled for you as an app developer behind the scenes. domain.add / domain.bind / domain.intercept are mostly for the use of a small subset of Node developers who maintain modules that use long-lived EventEmitters shared among a number of clients. If / when those modules are patched to work with domains, your need as an end user to deal with any of this stuff should vanish. At that point, yes, you should just be able to call domain.run() within your handlers and everything should Just Work. Sorry if I haven't made that clearer!

F


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
pie_lard  
View profile  
 More options Nov 14 2012, 6:24 pm
From: pie_lard <pie_l...@yahoo.com>
Date: Wed, 14 Nov 2012 15:24:44 -0800 (PST)
Local: Wed, Nov 14 2012 6:24 pm
Subject: Re: [nodejs] Domains and connection pools

Yes, we do agree - as an end user I should just have to use run().
 However, with my suggested approach the authors of the 3rd-party
connection pools and the like wouldn't have to change anything either.  As
it is it seems to me that they must go and add some code that simply checks
whether they are running under a domain and if so check they run any
callbacks under it.  In other words they must explicitly write behaviour
that could be implemented by default inside node.

 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Adam Crabtree  
View profile  
 More options Nov 14 2012, 6:26 pm
From: Adam Crabtree <atcrabt...@gmail.com>
Date: Wed, 14 Nov 2012 15:26:02 -0800
Local: Wed, Nov 14 2012 6:26 pm
Subject: Re: [nodejs] Domains and connection pools

FWIW, this is exactly why I built trycatch (
https://npmjs.org/package/trycatch). trycatch works for all the use cases
listed here:

* Call once, and all proceeding async calls and uncaught exceptions are
properly handled
* Nesting works as expected (exactly how nesting synchronous try/catch
blocks would behave)
* Not reliant on 3rd party modules to implement in order to work
* Long stack traces
* Works properly with EventEmitter

Granted, trycatch ATM doesn't offer the resource cleanup, but in theory it
could be combined with domains to accomplish this just fine. I may do so
when I get the chance now that domains are little more stable, assuming
they wouldn't interfere. In the other thread you mentioned above (
https://groups.google.com/forum/?fromgroups#!topic/nodejs/RphMf98jcgA)
where I'm discussing a few of these things, I included the following
example where domain nesting fails, but succeeds just fine with trycatch:

https://gist.github.com/4075399

Nothing against domains. I just find them to be cumbersome and to not solve
the problems I face, esp. wrt. libraries not properly handling
Errors/exceptions.

Cheers,
Adam Crabtree

On Wed, Nov 14, 2012 at 2:58 PM, Forrest L Norvell <forr...@newrelic.com>wrote:

--
Better a little with righteousness
       than much gain with injustice.
Proverbs 16:8

 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Forrest L Norvell  
View profile  
 More options Nov 14 2012, 6:28 pm
From: Forrest L Norvell <forr...@newrelic.com>
Date: Wed, 14 Nov 2012 15:28:17 -0800
Local: Wed, Nov 14 2012 6:28 pm
Subject: Re: [nodejs] Domains and connection pools

If the modules aren't patched to be domain-aware, then there's no way to ensure that the callback is evaluated in the correct domain. How do you think that would work?

F


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
pie_lard  
View profile  
 More options Nov 14 2012, 6:36 pm
From: pie_lard <pie_l...@yahoo.com>
Date: Wed, 14 Nov 2012 15:36:10 -0800 (PST)
Local: Wed, Nov 14 2012 6:36 pm
Subject: Re: [nodejs] Domains and connection pools

> If the modules aren't patched to be domain-aware, then there's no way to
> ensure that the callback is evaluated in the correct domain. How do you
> think that would work?

> F

To use my particular example - I've got a pool of node-mysql connections.
 Ultimately node-mysql is built on top of the node network socket API so
anytime a connection object fires a query off to the database it's doing so
with a low-level call to part of the node API - in the same way as
fs.read() or anything else.  If domains can persist when I just call
fs.read() or process.nextTick() - without having done any domain.add()s -
then they should also work when node-mysql does a network call.

 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Forrest L Norvell  
View profile  
 More options Nov 14 2012, 6:38 pm
From: Forrest L Norvell <forr...@newrelic.com>
Date: Wed, 14 Nov 2012 15:37:43 -0800
Local: Wed, Nov 14 2012 6:37 pm
Subject: Re: [nodejs] Domains and connection pools

On Wednesday, November 14, 2012 at 3:26 PM, Adam Crabtree wrote:
> FWIW, this is exactly why I built trycatch (https://npmjs.org/package/trycatch). trycatch works for all the use cases listed here:

> * Call once, and all proceeding async calls and uncaught exceptions are properly handled
> * Nesting works as expected (exactly how nesting synchronous try/catch blocks would behave)
> * Not reliant on 3rd party modules to implement in order to work
> * Long stack traces
> * Works properly with EventEmitter

> Granted, trycatch ATM doesn't offer the resource cleanup, but in theory it could be combined with domains to accomplish this just fine. I may do so when I get the chance now that domains are little more stable, assuming they wouldn't interfere. In the other thread you mentioned above (https://groups.google.com/forum/?fromgroups#!topic/nodejs/RphMf98jcgA) where I'm discussing a few of these things, I included the following example where domain nesting fails, but succeeds just fine with trycatch:

> https://gist.github.com/4075399

> Nothing against domains. I just find them to be cumbersome and to not solve the problems I face, esp. wrt. libraries not properly handling Errors/exceptions.

I made a few changes to your gist (the error wasn't getting handed off properly, and the domain error-handling code was looking for the properties that trycatch adds to the Error object):

  https://gist.github.com/4075562

In this example, everything behaves as it should (I believe) -- domainFoo calls thirdPartyFoo, so thirdPartyFoo's domain is active when the error is raised, and handles it, and then the callbacks are invoked, with the error ending up in the callback passed to domainFoo, as it should. Did my changes alter the point you were trying to make? If so, how?

F


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Forrest L Norvell  
View profile  
 More options Nov 14 2012, 6:43 pm
From: Forrest L Norvell <forr...@newrelic.com>
Date: Wed, 14 Nov 2012 15:43:08 -0800
Local: Wed, Nov 14 2012 6:43 pm
Subject: Re: [nodejs] Domains and connection pools

Forrest L Norvell
Node.js agent engineer
| E forr...@newrelic.com (mailto:forr...@newrelic.com) | C (415) 823‑6356 | T @othiym23 (http://twitter.com/othiym23) | G github.com/othiym23 (https://github.com/othiym23) | W newrelic.com (http://newrelic.com/)
( ( •))  New Relic

On Wednesday, November 14, 2012 at 3:36 PM, pie_lard wrote:
> > If the modules aren't patched to be domain-aware, then there's no way to ensure that the callback is evaluated in the correct domain. How do you think that would work?

> To use my particular example - I've got a pool of node-mysql connections.  Ultimately node-mysql is built on top of the node network socket API so anytime a connection object fires a query off to the database it's doing so with a low-level call to part of the node API - in the same way as fs.read() or anything else.  If domains can persist when I just call fs.read() or process.nextTick() - without having done any domain.add()s - then they should also work when node-mysql does a network call.

How does that persistence work? Put differently, how is Node supposed to know when a given EE is participating in a domain? You and I know that each individual node-mysql connection only handles a single query / response at a time, but other modules are going to multiplex on event emitters, and then you have to deal with the problem of figuring out which callback to associate with which domain.

F


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
pie_lard  
View profile  
 More options Nov 14 2012, 7:01 pm
From: pie_lard <pie_l...@yahoo.com>
Date: Wed, 14 Nov 2012 16:01:37 -0800 (PST)
Local: Wed, Nov 14 2012 7:01 pm
Subject: Re: [nodejs] Domains and connection pools

So, for example, node-mysql could be receiving callbacks because data has
arrived on a socket (or something like that - haven't looked and haven't
done any low-level IO in node ;) ).  And perhaps that data may turn out to
be part of the response to one of several in-flight queries (this is all
hypothetical).  So I guess node-mysql would in that case have to track
domains itself - that is, when query() is called by end-user code it would
have to store the value of process.domain along with whatever it needs to
track the call.

My point is that (a) that still doesn't involve binding a node-mysql
connection to a particular domain, which wouldn't help afaict and (b) many
modules presumably wouldn't have to do this if they aren't multiplexing
results in this way (I guess most aren't).

Sorry if this is all getting a bit long-winded.  I think I'm getting my
head around domains anyway!  


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Adam Crabtree  
View profile  
 More options Nov 14 2012, 7:03 pm
From: Adam Crabtree <atcrabt...@gmail.com>
Date: Wed, 14 Nov 2012 16:02:58 -0800
Local: Wed, Nov 14 2012 7:02 pm
Subject: Re: [nodejs] Domains and connection pools

You missed the point of the example about domain nesting failing.

`err.errors` is a mongoose thing, not a trycatch thing. It was my attempt
at a plausible uncaught exception in the strained example. The original
gist was correct:
https://gist.github.com/4075562/4c0e389da3e15048c2c99629eca28b8d96a7ebad

Nonetheless, the point stands that domain nesting doesn't work and the
process dies if you have an async error in a callback coming from a library
that uses domains, and had any sort of internal failure, a use-case in
which trycatch handles seemlessly.

Or to put it another way, it's not possible with domains (AFAIK) for
`domainFoo` to return an Error to its callback if the 3rd-party library
uses domains to return async errors, and as I mentioned in the other
thread, this is my primary use-case for async error-handling.

Also, FWIW, I'm highly critical of domains for all the reasons stated
above, but I also very much want a solution to the problem they solve. My
recommended solution (with code) is trycatch, and as you can see from this
thread, I'm not the only one that would prefer a much cleaner, simpler
solution to error handling in node.js.

That being said, I think node.js' error handling problem boils down to an
inability to catch asynchronous exceptions reliably, something
that's exacerbated by the lack of maturity of most 3rd-party libraries and
node.js' threadlessness and concurrency. uncaughtException is insufficient
as it loses context, and domains (at least currently) are insufficent for
the reasons stated above.

Cheers,
Adam Crabtree

On Wed, Nov 14, 2012 at 3:37 PM, Forrest L Norvell <forr...@newrelic.com>wrote:

--
Better a little with righteousness
       than much gain with injustice.
Proverbs 16:8

 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Forrest L Norvell  
View profile  
 More options Nov 14 2012, 7:30 pm
From: Forrest L Norvell <forr...@newrelic.com>
Date: Wed, 14 Nov 2012 16:29:55 -0800
Local: Wed, Nov 14 2012 7:29 pm
Subject: Re: [nodejs] Domains and connection pools

On Wednesday, November 14, 2012 at 4:02 PM, Adam Crabtree wrote:
> You missed the point of the example about domain nesting failing.

> `err.errors` is a mongoose thing, not a trycatch thing. It was my attempt at a plausible uncaught exception in the strained example. The original gist was correct: https://gist.github.com/4075562/4c0e389da3e15048c2c99629eca28b8d96a7ebad

> Nonetheless, the point stands that domain nesting doesn't work and the process dies if you have an async error in a callback coming from a library that uses domains, and had any sort of internal failure, a use-case in which trycatch handles seemlessly.

I see what you mean, and I see what the issue is. Not popping the domain where an error originates on a throw seems like a bug, not a purposeful omission or design decision.

Trycatch handles the core case of errors really well, but domains are a more general abstraction, and have a whole bunch of other applications. I use something very similar to domains (I need less than they offer, and I need to support versions of Node < 0.8) because I spent a while using hook.js from trycatch, and wasn't able to get it to handle a lot of the cases I needed (which were more about propagating state across an async call chain than capturing exceptions and errors. The potential I see in domains is that they're a very simple mechanism that nicely maps to the unique set of design choices embodied in Node (i.e. asynchronous with no standard promises, single threading, high concurrency).

> Or to put it another way, it's not possible with domains (AFAIK) for `domainFoo` to return an Error to its callback if the 3rd-party library uses domains to return async errors, and as I mentioned in the other thread, this is my primary use-case for async error-handling.

Yes. Anything that doesn't handle this case is an incomplete solution.
> Also, FWIW, I'm highly critical of domains for all the reasons stated above, but I also very much want a solution to the problem they solve. My recommended solution (with code) is trycatch, and as you can see from this thread, I'm not the only one that would prefer a much cleaner, simpler solution to error handling in node.js.

> That being said, I think node.js' error handling problem boils down to an inability to catch asynchronous exceptions reliably, something that's exacerbated by the lack of maturity of most 3rd-party libraries and node.js' threadlessness and concurrency. uncaughtException is insufficient as it loses context, and domains (at least currently) are insufficent for the reasons stated above.

I'm not sure all of those criteria can be addressed simultaneously without creating new problems. Trycatch isn't a lot of code, but there's a fair amount of complexity there, and shimming every call to process.nextTick, setTimeout, EventEmitters, et al is not without cost.

F


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Forrest L Norvell  
View profile  
 More options Nov 14 2012, 7:46 pm
From: Forrest L Norvell <forr...@newrelic.com>
Date: Wed, 14 Nov 2012 16:46:09 -0800
Local: Wed, Nov 14 2012 7:46 pm
Subject: Re: [nodejs] Domains and connection pools

On Wednesday, November 14, 2012 at 4:01 PM, pie_lard wrote:
> On Wednesday, 14 November 2012 23:43:27 UTC, Forrest L Norvell wrote:
> > How does that persistence work? Put differently, how is Node supposed to know when a given EE is participating in a domain? You and I know that each individual node-mysql connection only handles a single query / response at a time, but other modules are going to multiplex on event emitters, and then you have to deal with the problem of figuring out which callback to associate with which domain.

> So, for example, node-mysql could be receiving callbacks because data has arrived on a socket (or something like that - haven't looked and haven't done any low-level IO in node ;) ).  And perhaps that data may turn out to be part of the response to one of several in-flight queries (this is all hypothetical).  So I guess node-mysql would in that case have to track domains itself - that is, when query() is called by end-user code it would have to store the value of process.domain along with whatever it needs to track the call.

If you look at how domain.bind() is implemented (https://github.com/joyent/node/blob/v0.8/lib/domain.js#L148-L207), it wraps a closure around its callback, and all that closure does is ensure that process.domain and domain.active are set to the correct domain via domain.enter() (and cleared via domain.exit()) correctly before the callback is invoked. In effect, it's doing exactly what you describe, but in a DRY, general way.

> My point is that (a) that still doesn't involve binding a node-mysql connection to a particular domain, which wouldn't help afaict and (b) many modules presumably wouldn't have to do this if they aren't multiplexing results in this way (I guess most aren't).

In this case, binding a connection to a domain would definitely lead to incorrect behavior. I think in the vast majority of these cases domain.bind() is the best way ensure callbacks are evaluated in the correct domain. I apologize if I muddied the waters by bringing it up in the first place. ;)

> Sorry if this is all getting a bit long-winded.  I think I'm getting my head around domains anyway!  

I think that domains are going to remain obscure until enough people have banged their heads against them to figure out whether or not they're valuable, so conversations like this are useful. I apologize for taking such a long and roundabout way to explain things.

F


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Adam Crabtree  
View profile  
 More options Nov 14 2012, 7:49 pm
From: Adam Crabtree <atcrabt...@gmail.com>
Date: Wed, 14 Nov 2012 16:48:53 -0800
Local: Wed, Nov 14 2012 7:48 pm
Subject: Re: [nodejs] Domains and connection pools

Yup. That's true. Ideally if, possible, trycatch would find a way to
piggy-back on domains and forego shimming when performance matters
(production) and lose probably just long-stack traces. Also, although
shimming has a cost, it's negligible compared to crashing and restarting
and IMHO is negligible compared to other performance hits like using
promises, though should probably run some hard benchmarks. Domains
themselves add a similar cost, requiring a constant tracking and switching
of the active domain. Trycatch is highly optimized, though. Sounds like an
opportunity for a performance comparison.

Again, my ultimate desire is for someone else to do the heavy lifting in
core, and to then piggy-back the trycatch API on top. As it stands now, it
doesn't look like that would be possible, though it seems close.

I'd love to hear your comparison of what exactly domains offer apart from
the error-handling that trycatch offers. I know generally about the
low-level resource cleanup like open fd and sockets, etc..., but perhaps
you could go into detail? While rummaging through the source, my primary
interest was more on how it was implemented than the additional features.

Cheers,
Adam Crabtree


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Jake Verbaten  
View profile  
 More options Nov 14 2012, 9:24 pm
From: Jake Verbaten <rayn...@gmail.com>
Date: Wed, 14 Nov 2012 18:24:13 -0800
Local: Wed, Nov 14 2012 9:24 pm
Subject: Re: [nodejs] Domains and connection pools

Why does it fail?


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Forrest L Norvell  
View profile  
 More options Nov 14 2012, 9:38 pm
From: Forrest L Norvell <forr...@newrelic.com>
Date: Wed, 14 Nov 2012 18:37:57 -0800
Local: Wed, Nov 14 2012 9:37 pm
Subject: Re: [nodejs] Domains and connection pools

On Wednesday, November 14, 2012 at 6:24 PM, Jake Verbaten wrote:
> > https://gist.github.com/4075562/4c0e389da3e15048c2c99629eca28b8d96a7ebad
> Why does it fail?

When the code running inside (the inner) domain d1 throws and d1's error handler calls the callback from (the outer) domain d2 with the error, the error in d2's callback gets emitted on d1's error handler because d1 wasn't cleanly exited. Either domain.bind() needs to run its callback inside a try / catch / finally block that emits the error on the domain handler and then exits the domain, or the uncaughtException handler installed by the domain module needs to figure out how to clean up the domain's state. The former seems a lot simpler, and would fix this problem for domain.run, domain.bind and domain.intercept, which is probably good enough for now and keeps everything relatively simple (although it incurs the overhead of v8 not being able to optimize try-catch blocks).

F


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Messages 1 - 25 of 28   Newer >
« Back to Discussions « Newer topic     Older topic »