UNPKG

ickyrr-gagarin

Version:

A current updated fork of gagarin

113 lines (83 loc) 3.4 kB
var MongoClient = require('mongodb').MongoClient; var findAvailablePort = require('../tools').findAvailablePort; var debounce = require('debounce'); var Promise = require('es6-promise').Promise; var mkdirp = require('mkdirp'); var spawn = require('child_process').spawn; var path = require('path'); var tools = require('../tools'); var either = tools.either; var fs = require('fs'); var myMongoServerPromises = {}; module.exports = function MongoDBProcess (options) { "use strict"; options = options || {}; var pathToApp = options.pathToApp || path.resolve('.'); if (myMongoServerPromises[pathToApp]) { // XXX there can be only one mongo process using the given database path return myMongoServerPromises[pathToApp]; } var pathToGitIgnore = tools.getPathToGitIgnore(pathToApp); var mongoPort = options.dbPort; var pathToDB = options.dbPath || tools.getPathToDB(pathToApp); //------------------------------------------------------------------------- myMongoServerPromises[pathToApp] = new Promise(function (resolve, reject) { Promise.all([ // find mongodb executable tools.getMongoPath(pathToApp), // find available port or use the one provided by user mongoPort ? Promise.resolve(mongoPort) : findAvailablePort() ]).then(function (results) { var mongoPath = results[0]; mongoPort = results[1]; if (!fs.existsSync(mongoPath)) { throw new Error('file ' + mongoPath + ' does not exists'); } var mongoUrl = 'mongodb://127.0.0.1:' + mongoPort; var mongoArgs = [ '--port', mongoPort, '--smallfiles', '--nojournal', '--noprealloc' ]; try { if (!fs.existsSync(pathToGitIgnore)) { // make sure the directory exists mkdirp.sync(path.dirname(pathToGitIgnore)); // make sure "local" directory is ignored by git fs.writeFileSync(pathToGitIgnore, 'local'); } mkdirp.sync(pathToDB); } catch (err) { return reject(err); } pathToDB && mongoArgs.push('--dbpath', path.resolve(pathToDB)); var mongoProcess = spawn(mongoPath || 'mongod', mongoArgs); // use debounce to give the process some time in case it exits prematurely var numberOfRetries = 10; function connectWithRetry () { if (numberOfRetries < 0) { return reject(new Error('cannot connect to ' + mongoUrl + '... giving up')); } MongoClient.connect(mongoUrl + '/test', function (err, db) { if (err) { setTimeout(connectWithRetry, 100); } else { db.close(function () { resolve(mongoUrl); }); } }); }; mongoProcess.stdout.on('data', debounce(tools.once(connectWithRetry), 1000)); // TODO: get rid of this log before the next release mongoProcess.stderr.on('data', function (data) { console.log(data.toString()); }); // on premature exit, reject the promise mongoProcess.on('exit', function (code) { code && reject(new Error("mongo exited with code: " + code)); }); // make sure mongoProcess is killed if the parent process exits process.on('exit', function () { mongoProcess.kill(); }); }).catch(reject); }); // new Promise return myMongoServerPromises[pathToApp]; };