On Domains and Connections with node.js

Posted: 13 Dec 2012
Categories: node.js software engineering

Click to expand

Solved!

The reason for this question was to ensure that in actionHero exceptions thrown after a call to the api.cache methods would still be caught by the domain they should have been in. Here is the commit which force-binds callbacks from the redis client back to the domain they should have been in. This is needed due to the fact that connection-pooled clients (which were created before the domain) will always revert back to their original scope.


The Question:

I've been having trouble lately with domains in node.js, in that I have found a few occasions where what is 'in scope' confuses me. Here's a collection of tests to illustrate my I set up the test to have a domain which I will run each test in, and I expect all of the tests to throw an error and to be caught by the domain's on('error') event. I chose to use a redis client here (because it's common), but I do not think that this is a problem with the awesome redis package, and I've observed similar behavior with the mysql / seq All of the tests work except #4, which throws an out-of-domain exception and causes the script to crash

 1 var domain = require('domain');
 2 var redis = require('redis');
 3 var eventEmitter = require('events').EventEmitter;
 4  
 5 var tests = [];
 6 var testCounter = 0;
 7 var runTest = function(){
 8   if(tests.length > testCounter){
 9     tests[testCounter]();
10   }else{
11     console.log("all done!")
12     process.exit();
13   }
14 }
15  
16 var myDomain = new domain.create();
17 myDomain.on('error', function(err){
18   console.log('Yo, I just saved you from the error: ' + err);
19   testCounter++;
20   runTest();
21 });
22  
23 // PASSING
24 tests[0] = function(){
25   myDomain.run(function(){
26     throw new Error('A simple error');
27   });
28 };
29  
30 // PASSING
31 tests[1] = function(){
32   myDomain.run(function(){
33     setTimeout(function(){
34       process.nextTick(function(){
35         var E = new eventEmitter;
36         E.on('thing', function(){
37           throw new Error('A deeply nested error');
38         })
39         setTimeout(function(){
40           E.emit('thing');
41         }, 100)
42       });
43     }, 100);
44   });
45 }
46  
47 // PASSING
48 var Emm = new eventEmitter;
49 Emm.on('thing', function(){
50   throw new Error('Emmited Error defined outside of scope');
51 })
52 tests[2] = function(){
53   myDomain.run(function(){
54   setTimeout(function(){
55       Emm.emit('thing');
56     }, 100)
57   })
58 };
59  
60 // PASSING
61 tests[3] = function(){
62   myDomain.run(function(){
63     clientA = redis.createClient();
64     clientA.hget('hash', 'key', function(err, data){
65       throw new Error('An error after redis (A)');
66     });
67   });
68 }
69  
70 // PASSING
71 tests[4] = function(){
72   clientB = redis.createClient();
73   myDomain.run(function(){
74     clientB.hget('hash', 'key', function(err, data){
75       throw new Error('An error after redis (B)');
76     });
77   });
78 };
79  
80 // FAILING
81 clientC = redis.createClient();
82 tests[5] = function(){
83   myDomain.run(function(){
84     clientC.hget('hash', 'key', function(err, data){
85       throw new Error('An error after redis (C)');
86     });
87   });
88 };
89  
90 // start it up
91 runTest();

In all of these cases, I would have hoped for the domain to catch the exceptions. I also would have also expected tests #4 and #5 to behave the same way regardless of whether or n Can anyone help me to explain why test 5 fails? domain can have their exceptions caught by it. Cross-Posted on GitHub


<< What do you do when softpedia scrapes you projects? Delete old git branches already merged into master >>



Follow me on Twitter Follow me on Github



Categories

comments powered by Disqus