Skip to content

Instantly share code, notes, and snippets.

@AndreasMadsen
Created June 10, 2012 09:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AndreasMadsen/2904724 to your computer and use it in GitHub Desktop.
Save AndreasMadsen/2904724 to your computer and use it in GitHub Desktop.
domain bug and design?
var domain = require('domain');
var url = require('url');
var util = require('util');
var events = require('events');
/* hack */
domain.Domain.prototype.run = function (fn) {
var active = this;
// sync thrown errors needs be be catch and deleayed by process.nextTick.
// This allow the function (fn) to return an error handler.
try {
return active.bind(fn)();
} catch (er) {
util._extend(er, {
domain: active,
domain_thrown: true
});
process.nextTick(function () {
active.emit('error', er);
});
}
};
/* */
function Request(req, res) {
events.EventEmitter.call(this);
// lets hope this is safe :D
var self = this;
this.domain = domain.create();
// add http request objects to domain
this.req = req;
this.res = res;
// this will acturlly throw because it checks req.domain
// unless we do the if check
if (req) this.domain.add(req);
if (res) this.domain.add(res);
// any domain error will be relayed to the request object itself
this.domain.on('error', function (error) {
// !!! - is this a bug? - fix is below
// No matter how much this is delayed it will throw and result in
// an infinity event loop, because the constructor never returned
// its own this object.
// setTimeout(function() {
// The only way to go around this is to wrap domain.rum in an try
// catch, but the purpose of domain is not to do that. At least
// not manually. See hack above!
self.emit('error', error);
//}, 200);
});
// any error should be catched
return this.domain.run((function () {
this.internal();
}).bind(this));
}
util.inherits(Request, events.EventEmitter);
Request.prototype.internal = function () {
this.url = url.parse(this.req.url);
};
// !!! - is there a better pattern?
// execute function (fn) in domain wrapper, use it only on public functions
function wrap(fn) {
return function () {
// Note that in this case, the try catch inside the domain.run hack
// has no purpose, since the user has time to attach an error handler.
this.domain.run(fn.bind(this));
};
}
Request.prototype.parse = wrap(function () {
return this.url.hostname;
});
Request.prototype.destroy = wrap(function () {
this.domain.dispose();
});
/// require land
// Somehow it happend that req wasn't set
// It dosn't matter how, this is just an example
var r = new Request(undefined, undefined);
// lets attach an error handler as fast as possibol
r.on('error', function (error) {
console.error(error.stack);
r.destroy();
});
// will fail since r.url is undefined
console.log('url parse:', r.parse());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment