Wait for mongo to listen on port before starting server. Fixes #991 (#996)

* WIP #991

* WIP #991 wait for mongo to listen on the given port

* WIP #991 refactored to make more testable

* WIP #991 fixed port bug

* WIP #991 added test for mongodb start race cond
Esse commit está contido em:
Brian Broll
2017-03-23 15:34:51 -05:00
commit de GitHub
commit c8e9dfd0e0
3 arquivos alterados com 74 adições e 36 exclusões
+40 -28
Ver Arquivo
@@ -1,6 +1,7 @@
#!/usr/bin/env node
var Command = require('commander').Command,
tcpPortUsed = require('tcp-port-used'),
program = new Command(),
childProcess = require('child_process'),
rawSpawn = childProcess.spawn,
@@ -118,32 +119,35 @@ var isLocalUri = function(protocol, uri) {
uri.indexOf(protocol + '://127.0.0.1') === 0;
};
var checkMongo = function(args, notSilent) {
var checkMongo = function(args, notSilent, mongoUri) {
// check the webgme config
var gmeConfig = require('../config'),
mongoUri = gmeConfig.mongo.uri;
var gmeConfig = require('../config');
mongoUri = mongoUri || gmeConfig.mongo.uri;
if (isLocalUri('mongodb', mongoUri)) {
var match = mongoUri.match(/:([0-9]+)/),
port = '80';
if (match) {
port = match[1];
}
// Make sure mongo is running locally (using pgrep)
try {
execSync('pgrep mongod').toString();
console.log('MongoDB is already running!');
} catch (e) { // no pIds
console.log('Starting MongoDB...');
var match = mongoUri.match(/:([0-9]+)/),
port = '80';
if (match) {
port = match[1];
}
startMongo(args, port, !notSilent);
}
return tcpPortUsed.waitUntilUsed(+port, 100, 1000);
} else if (notSilent) {
console.log(`Cannot start remote mongo locally: ${mongoUri}`);
} else {
console.log(`Using remote mongo: ${mongoUri}`);
}
return Q();
};
var startMongo = function(args, port, silent) {
@@ -294,42 +298,49 @@ program.command('start')
.option('-w, --worker [url]', 'start a worker and connect to given url. Defaults to local deepforge')
.option('-m, --mongo', 'start MongoDB')
.action(args => {
var main = path.join(__dirname, 'start-local.js');
var main = path.join(__dirname, 'start-local.js'),
current = Q();
if (args.port) {
process.env.PORT = args.port;
}
if (args.mongo) {
current = current.then(() => checkMongo(args, true));
}
if (args.server) {
checkMongo(args);
main = path.join(__dirname, '..', 'app.js');
spawn('node', [main]);
current = current
.then(() => checkMongo(args))
.then(() => {
main = path.join(__dirname, '..', 'app.js');
return spawn('node', [main]);
});
}
if (args.worker) {
if (hasTorch()) {
installTorchExtras().then(() => {
main = path.join(__dirname, 'start-worker.js');
if (args.worker !== true) {
spawn('node', [main, args.worker]);
} else {
spawn('node', [main]);
}
});
current
.then(() => installTorchExtras())
.then(() => {
main = path.join(__dirname, 'start-worker.js');
if (args.worker !== true) {
spawn('node', [main, args.worker]);
} else {
spawn('node', [main]);
}
});
} else {
installTorch();
}
}
if (args.mongo) {
checkMongo(args, true);
}
if (!args.server && !args.worker && !args.mongo) {
// Starting everything
checkMongo(args);
current = current.then(() => checkMongo(args));
if (hasTorch()) {
installTorchExtras().then(() => spawn('node', [main]));
current.then(() => installTorchExtras())
.then(() => spawn('node', [main]));
} else {
installTorch();
}
@@ -475,6 +486,7 @@ module.exports = function(cmd) {
cmds.unshift('node');
program.parse(cmds);
};
module.exports.checkMongo = checkMongo;
if (require.main === module) {
program.parse(process.argv);
+3 -2
Ver Arquivo
@@ -1,8 +1,8 @@
{
"name": "deepforge",
"repository": {
"type": "git",
"url": "https://github.com/deepforge-dev/deepforge.git"
"type": "git",
"url": "https://github.com/deepforge-dev/deepforge.git"
},
"bin": {
"deepforge": "./bin/deepforge"
@@ -32,6 +32,7 @@
"npm": "^4.0.5",
"q": "1.4.1",
"rimraf": "^2.4.0",
"tcp-port-used": "^0.1.2",
"webgme": "^2.7.1",
"webgme-autoviz": "^2.2.0",
"webgme-breadcrumbheader": "^2.1.1",
+31 -6
Ver Arquivo
@@ -81,12 +81,37 @@ describe('cli', function() {
cli = require('../../bin/deepforge');
});
it('should check for running mongo', function() {
var calls;
callRegister.childProcess.execSync = [];
cli('start');
calls = callRegister.childProcess.execSync;
assert.notEqual(calls.indexOf('pgrep mongod'), -1);
it('should check for running mongo', function(done) {
var mongoListening = false,
mongoUri = 'mongodb://127.0.0.1:2016/deepforge-test',
net = require('net'),
server = net.createServer(function(socket) {
socket.on('error', err => {
// Only worry about mock server errors if the test hasn't completed
assert(mongoListening);
});
socket.pipe(socket);
}),
mockStartMongo = function(port) {
server.listen(+port, '127.0.0.1');
mongoListening = true;
};
// Check that 'spawn' node happens after the tcp port has been bound
mocks.childProcess.spawn = function(cmd, opts) {
if (cmd === 'mongod') {
setTimeout(mockStartMongo, 250, opts[3]);
}
};
cli.checkMongo({}, false, mongoUri)
.then(() => {
console.log('closing server');
server.close();
assert(mongoListening);
done();
})
.catch(err => console.error(err));
});
it('should start mongo if no running mongo', function() {