Skip to content

Instantly share code, notes, and snippets.

@owenallenaz
Created July 27, 2016 19:26
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 owenallenaz/5111ac4dd1fdc9564e15c25dfc443cd9 to your computer and use it in GitHub Desktop.
Save owenallenaz/5111ac4dd1fdc9564e15c25dfc443cd9 to your computer and use it in GitHub Desktop.
process.nextTick is required for proper domain entrance and preventing leaking of domains

In the following test code there are two things to look for.

"in cb 0 0 1" means that it is in the callback after the call to mongodb, and the numbers are "expectedNum actualNum stackSize". The expectedNum and actualNum match, and they do. The stackSize should always be 1. In the event the stackSize is not 1 it means that the domains are not being properly entered and exited. If the stackSize grows domains are leaking.

Another important marker is the "after exit" and "end call" blocks, they should always be undefined. In the event that they are not undefined it means that a domain is lingering after exit, which results in subsequent code being in a domain it shouldn't, as well as a possible memory leak.

From the test file it appears that both setImmediate and process.nextTick() work.

var mongodb = require("mongodb");
var domain = require("domain");
var logs = [];
mongodb.MongoClient.connect("mongodb://localhost:27017/test_owen", { server : { poolSize : 2 } }, function(err, db) {
var startUp = function(cb) {
var d = domain.create();
d.run(function() {
process.nextTick(function() {
db.collection("foo").find({}).toArray(function(err, docs) {
db.collection("foo").find({}).toArray(function(err, docs) {
db.collection("foo").find({}).toArray(function(err, docs) {
db.collection("foo").find({}).toArray(function(err, docs) {
db.collection("foo").find({}).toArray(function(err, docs) {
d.exit();
process.nextTick(function() {
cb(null);
});
});
});
});
});
});
});
});
}
startUp(function() {
console.log("domain.active2", domain.active);
var calls = [];
for (var i = 0; i < 20; i++) {
(function(i) {
calls.push(function(cb) {
logs.push(["start call", i, domain.active ? domain.active._num : undefined]);
var d = domain.create();
d.on("error", function(e) {
console.log("caught it!", i, e);
d.exit();
process.nextTick(function() {
cb(null);
});
});
d._num = i;
d.run(function() {
logs.push(["before tick", i, domain.active._num]);
process.nextTick(function() {
logs.push(["in run", i, domain.active._num])
db.collection("foo").find({}).toArray(function(err, docs) {
console.log("in cb", i, domain.active ? domain.active._num : undefined, domain._stack.length);
d.exit();
logs.push(["after exit", i, domain.active ? domain.active._num : undefined]);
process.nextTick(function() {
logs.push(["end call", i, domain.active ? domain.active._num : undefined]);
cb(null);
});
});
});
});
});
})(i);
}
calls.forEach(function(val, i) {
setTimeout(function() {
val(function() {});
}, 1);
});
});
});
setTimeout(function() {
console.log("logs", logs);
}, 1000);
Notice that the after exit and end call always have an undefined domain. This domain that the domain has been properly exited.
Also at the top you can see that "in cb expectedDom actualNum stackSize" the stackSize is always 1. Indicating that domains are
being properly entered and exited.
in cb 0 0 1
in cb 1 1 1
in cb 2 2 1
in cb 4 4 1
in cb 3 3 1
in cb 5 5 1
in cb 6 6 1
in cb 7 7 1
in cb 8 8 1
in cb 9 9 1
in cb 10 10 1
in cb 11 11 1
in cb 12 12 1
in cb 13 13 1
in cb 14 14 1
in cb 15 15 1
in cb 16 16 1
in cb 17 17 1
in cb 18 18 1
in cb 19 19 1
logs [ [ 'start call', 0, undefined ],
[ 'before tick', 0, 0 ],
[ 'start call', 1, undefined ],
[ 'before tick', 1, 1 ],
[ 'start call', 2, undefined ],
[ 'before tick', 2, 2 ],
[ 'start call', 3, undefined ],
[ 'before tick', 3, 3 ],
[ 'start call', 4, undefined ],
[ 'before tick', 4, 4 ],
[ 'start call', 5, undefined ],
[ 'before tick', 5, 5 ],
[ 'start call', 6, undefined ],
[ 'before tick', 6, 6 ],
[ 'start call', 7, undefined ],
[ 'before tick', 7, 7 ],
[ 'start call', 8, undefined ],
[ 'before tick', 8, 8 ],
[ 'start call', 9, undefined ],
[ 'before tick', 9, 9 ],
[ 'start call', 10, undefined ],
[ 'before tick', 10, 10 ],
[ 'start call', 11, undefined ],
[ 'before tick', 11, 11 ],
[ 'start call', 12, undefined ],
[ 'before tick', 12, 12 ],
[ 'start call', 13, undefined ],
[ 'before tick', 13, 13 ],
[ 'start call', 14, undefined ],
[ 'before tick', 14, 14 ],
[ 'start call', 15, undefined ],
[ 'before tick', 15, 15 ],
[ 'start call', 16, undefined ],
[ 'before tick', 16, 16 ],
[ 'start call', 17, undefined ],
[ 'before tick', 17, 17 ],
[ 'start call', 18, undefined ],
[ 'before tick', 18, 18 ],
[ 'start call', 19, undefined ],
[ 'before tick', 19, 19 ],
[ 'in run', 0, 0 ],
[ 'in run', 1, 1 ],
[ 'in run', 2, 2 ],
[ 'in run', 3, 3 ],
[ 'in run', 4, 4 ],
[ 'in run', 5, 5 ],
[ 'in run', 6, 6 ],
[ 'in run', 7, 7 ],
[ 'in run', 8, 8 ],
[ 'in run', 9, 9 ],
[ 'in run', 10, 10 ],
[ 'in run', 11, 11 ],
[ 'in run', 12, 12 ],
[ 'in run', 13, 13 ],
[ 'in run', 14, 14 ],
[ 'in run', 15, 15 ],
[ 'in run', 16, 16 ],
[ 'in run', 17, 17 ],
[ 'in run', 18, 18 ],
[ 'in run', 19, 19 ],
[ 'after exit', 0, undefined ],
[ 'end call', 0, undefined ],
[ 'after exit', 1, undefined ],
[ 'end call', 1, undefined ],
[ 'after exit', 2, undefined ],
[ 'end call', 2, undefined ],
[ 'after exit', 4, undefined ],
[ 'end call', 4, undefined ],
[ 'after exit', 3, undefined ],
[ 'end call', 3, undefined ],
[ 'after exit', 5, undefined ],
[ 'end call', 5, undefined ],
[ 'after exit', 6, undefined ],
[ 'end call', 6, undefined ],
[ 'after exit', 7, undefined ],
[ 'end call', 7, undefined ],
[ 'after exit', 8, undefined ],
[ 'end call', 8, undefined ],
[ 'after exit', 9, undefined ],
[ 'end call', 9, undefined ],
[ 'after exit', 10, undefined ],
[ 'end call', 10, undefined ],
[ 'after exit', 11, undefined ],
[ 'end call', 11, undefined ],
[ 'after exit', 12, undefined ],
[ 'end call', 12, undefined ],
[ 'after exit', 13, undefined ],
[ 'end call', 13, undefined ],
[ 'after exit', 14, undefined ],
[ 'end call', 14, undefined ],
[ 'after exit', 15, undefined ],
[ 'end call', 15, undefined ],
[ 'after exit', 16, undefined ],
[ 'end call', 16, undefined ],
[ 'after exit', 17, undefined ],
[ 'end call', 17, undefined ],
[ 'after exit', 18, undefined ],
[ 'end call', 18, undefined ],
[ 'after exit', 19, undefined ],
[ 'end call', 19, undefined ] ]
in cb 0 0 1
in cb 1 1 1
in cb 2 2 1
in cb 4 4 1
in cb 3 3 2
in cb 5 5 1
in cb 6 6 2
in cb 7 7 1
in cb 8 8 2
in cb 9 9 1
in cb 10 10 2
in cb 11 11 1
in cb 12 12 2
in cb 13 13 1
in cb 14 14 2
in cb 15 15 1
in cb 16 16 2
in cb 17 17 1
in cb 18 18 2
in cb 19 19 1
logs [ [ 'start call', 0, undefined ],
[ 'before tick', 0, 0 ],
[ 'start call', 1, undefined ],
[ 'before tick', 1, 1 ],
[ 'start call', 2, undefined ],
[ 'before tick', 2, 2 ],
[ 'start call', 3, undefined ],
[ 'before tick', 3, 3 ],
[ 'start call', 4, undefined ],
[ 'before tick', 4, 4 ],
[ 'start call', 5, undefined ],
[ 'before tick', 5, 5 ],
[ 'start call', 6, undefined ],
[ 'before tick', 6, 6 ],
[ 'start call', 7, undefined ],
[ 'before tick', 7, 7 ],
[ 'start call', 8, undefined ],
[ 'before tick', 8, 8 ],
[ 'start call', 9, undefined ],
[ 'before tick', 9, 9 ],
[ 'start call', 10, undefined ],
[ 'before tick', 10, 10 ],
[ 'start call', 11, undefined ],
[ 'before tick', 11, 11 ],
[ 'start call', 12, undefined ],
[ 'before tick', 12, 12 ],
[ 'start call', 13, undefined ],
[ 'before tick', 13, 13 ],
[ 'start call', 14, undefined ],
[ 'before tick', 14, 14 ],
[ 'start call', 15, undefined ],
[ 'before tick', 15, 15 ],
[ 'start call', 16, undefined ],
[ 'before tick', 16, 16 ],
[ 'start call', 17, undefined ],
[ 'before tick', 17, 17 ],
[ 'start call', 18, undefined ],
[ 'before tick', 18, 18 ],
[ 'start call', 19, undefined ],
[ 'before tick', 19, 19 ],
[ 'in run', 0, 0 ],
[ 'in run', 1, 1 ],
[ 'in run', 2, 2 ],
[ 'in run', 3, 3 ],
[ 'in run', 4, 4 ],
[ 'in run', 5, 5 ],
[ 'in run', 6, 6 ],
[ 'in run', 7, 7 ],
[ 'in run', 8, 8 ],
[ 'in run', 9, 9 ],
[ 'in run', 10, 10 ],
[ 'in run', 11, 11 ],
[ 'in run', 12, 12 ],
[ 'in run', 13, 13 ],
[ 'in run', 14, 14 ],
[ 'in run', 15, 15 ],
[ 'in run', 16, 16 ],
[ 'in run', 17, 17 ],
[ 'in run', 18, 18 ],
[ 'in run', 19, 19 ],
[ 'after exit', 0, undefined ],
[ 'end call', 0, undefined ],
[ 'after exit', 1, undefined ],
[ 'end call', 1, undefined ],
[ 'after exit', 2, undefined ],
[ 'end call', 2, undefined ],
[ 'after exit', 4, undefined ],
[ 'end call', 4, undefined ],
[ 'after exit', 3, 1 ],
[ 'end call', 3, 1 ],
[ 'after exit', 5, undefined ],
[ 'end call', 5, undefined ],
[ 'after exit', 6, 1 ],
[ 'end call', 6, 1 ],
[ 'after exit', 7, undefined ],
[ 'end call', 7, undefined ],
[ 'after exit', 8, 1 ],
[ 'end call', 8, 1 ],
[ 'after exit', 9, undefined ],
[ 'end call', 9, undefined ],
[ 'after exit', 10, 1 ],
[ 'end call', 10, 1 ],
[ 'after exit', 11, undefined ],
[ 'end call', 11, undefined ],
[ 'after exit', 12, 1 ],
[ 'end call', 12, 1 ],
[ 'after exit', 13, undefined ],
[ 'end call', 13, undefined ],
[ 'after exit', 14, 1 ],
[ 'end call', 14, 1 ],
[ 'after exit', 15, undefined ],
[ 'end call', 15, undefined ],
[ 'after exit', 16, 1 ],
[ 'end call', 16, 1 ],
[ 'after exit', 17, undefined ],
[ 'end call', 17, undefined ],
[ 'after exit', 18, 1 ],
[ 'end call', 18, 1 ],
[ 'after exit', 19, undefined ],
[ 'end call', 19, undefined ] ]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment