Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

domain.dispose() before next(err) #8

Merged
merged 1 commit into from

2 participants

@fengmk2

No description provided.

@fengmk2

@baryshev Please review this when you're free.

@baryshev
Owner

Sorry for slow response. Changing on to once may cause aplication crash if more than one errors occurred inside of request.

Simple test case:

var async = require('async');
var http = require('http');
var connect = require('connect');
var app = connect();
var connectDomain = require('connect-domain');
app.use(connectDomain());
app.use(function (req, res) {
    async.parallel([function (cb) {
        setTimeout(function () {
            throw new Error('test1');
            cb();
        }, 1000);
    }, function (cb) {
        setTimeout(function () {
            throw new Error('test2');
            cb();
        }, 1100);
    }], function () {
        res.writeHead(200, {'Content-Type': 'text/plain'});
        res.end('Hello World\n');
    });
});

app.use(function (err, req, res) {
    res.end(err.message);
});

http.createServer(app).listen(1339, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1339/');
@baryshev
Owner

About removing reqDomain.dispose(). I'm not sure that's a good idea. I think we need to add reqDomain.dispose() to error handler and hook res.end like this:

res.end = function () {
    reqDomain.dispose();
    res.end.apply(this, arguments);
};

to dispose domain in all situations. dispose removing all event listeners from domain which make garbage collector work more simpler.

@fengmk2

We only using "Implicit Binding" mode, domain.dispose() will be auto executed.

If you want to nest Domain objects as children of a parent Domain, then you must explicitly add them, and then dispose of them later.

Only on "Explicit Binding" mode, we need to call dispose() by ourself.

@fengmk2

If more than one errors occurred inside of request, we should only send one error response to request user.

@baryshev
Owner

Yes, we need to send only one error to user, but if we use .once application will crash after second error in the same request. You can check this with code example from my first comment. I use node 0.8.22.

@baryshev
Owner

domain.dispose() never called automatically. It can be checked by adding listener to domain dispose event. So if we have to cleanup unnecessary domains we need to call .dispose() at all of them.

@fengmk2

@baryshev I rebase the code and add async error appear twice test cases.

@baryshev baryshev merged commit 9066460 into baryshev:master
@fengmk2 fengmk2 deleted the fengmk2:remove-dispose branch
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Mar 12, 2013
  1. @fengmk2
This page is out of date. Refresh to see the latest.
Showing with 23 additions and 2 deletions.
  1. +5 −1 lib/connect-domain.js
  2. +18 −1 test/domain.test.js
View
6 lib/connect-domain.js
@@ -8,7 +8,11 @@ module.exports = function () {
reqDomain.dispose();
});
- reqDomain.on('error', next);
+ reqDomain.on('error', function (err) {
+ // Once a domain is disposed, further errors from the emitters in that set will be ignored.
+ reqDomain.dispose();
+ next(err);
+ });
reqDomain.run(next);
};
View
19 test/domain.test.js
@@ -26,6 +26,15 @@ describe('domain.test.js', function () {
});
return;
}
+ if (req.url === '/async_error_twice') {
+ setTimeout(function () {
+ ff.foo();
+ }, 100);
+ setTimeout(function () {
+ bar.bar();
+ }, 210);
+ return;
+ }
res.end(req.url);
};
@@ -60,9 +69,10 @@ describe('domain.test.js', function () {
before(function () {
mochaHandler = process.listeners('uncaughtException').pop();
});
- after(function () {
+ after(function (done) {
// ...but be sure to re-enable mocha's error handler
process.on('uncaughtException', mochaHandler);
+ setTimeout(done, 500);
});
it('should GET /async_error status 500', function (done) {
@@ -71,6 +81,13 @@ describe('domain.test.js', function () {
.expect('ff is not defined')
.expect(500, done);
});
+
+ it('should GET /async_error_twice status 500', function (done) {
+ request(app)
+ .get('/async_error_twice')
+ .expect('ff is not defined')
+ .expect(500, done);
+ });
});
});
Something went wrong with that request. Please try again.