From 7424bb63cd741fb6a75cbb0885a394bc5194fad5 Mon Sep 17 00:00:00 2001 From: David Glasser Date: Thu, 19 Dec 2013 17:25:02 -0800 Subject: [PATCH] mongo_runner: Don't send rs.initiate too early Fixes #1696. Thanks to @Maxpain177 for reporting and providing access to a machine where this was easily reproducible. --- tools/mongo_runner.js | 67 ++++++++++++++++++++++++++++++------------- 1 file changed, 47 insertions(+), 20 deletions(-) diff --git a/tools/mongo_runner.js b/tools/mongo_runner.js index 40d0a39bf8..09a3efbacf 100644 --- a/tools/mongo_runner.js +++ b/tools/mongo_runner.js @@ -234,6 +234,8 @@ exports.launchMongo = function (options) { proc.stdout.setEncoding('utf8'); var listening = false; var replSetReady = false; + var replSetReadyToBeInitiated = false; + var alreadyInitiatedReplSet = false; var maybeCallOnListen = function () { if (listening && replSetReady) { if (createReplSet) @@ -241,29 +243,54 @@ exports.launchMongo = function (options) { onListen(); } }; + + var maybeInitiateReplset = function () { + // We need to want to create a replset, be confident that the server is + // listening, be confident that the server's replset implementation is + // ready to be initiated, and have not already done it. + if (!(createReplSet && listening && replSetReadyToBeInitiated + && !alreadyInitiatedReplSet)) { + return; + } + + alreadyInitiatedReplSet = true; + + // Connect to it and start a replset. + var db = new mongoNpmModule.Db( + 'meteor', new mongoNpmModule.Server('127.0.0.1', options.port), + {safe: true}); + db.open(function(err, db) { + if (err) + throw err; + db.admin().command({ + replSetInitiate: { + _id: replSetName, + members: [{_id : 0, host: '127.0.0.1:' + options.port}] + } + }, function (err, result) { + if (err) + throw err; + // why this isn't in the error is unclear. + if (result && result.documents && result.documents[0] + && result.documents[0].errmsg) { + throw result.document[0].errmsg; + } + db.close(true); + }); + }); + }; + proc.stdout.on('data', function (data) { + // note: don't use "else ifs" in this, because 'data' can have multiple + // lines + if (/config from self or any seed \(EMPTYCONFIG\)/.test(data)) { + replSetReadyToBeInitiated = true; + maybeInitiateReplset(); + } + if (/ \[initandlisten\] waiting for connections on port/.test(data)) { - if (createReplSet) { - // Connect to it and start a replset. - var db = new mongoNpmModule.Db( - 'meteor', new mongoNpmModule.Server('127.0.0.1', options.port), - {safe: true}); - db.open(function(err, db) { - if (err) - throw err; - db.admin().command({ - replSetInitiate: { - _id: replSetName, - members: [{_id : 0, host: '127.0.0.1:' + options.port}] - } - }, function (err, result) { - if (err) - throw err; - db.close(true); - }); - }); - } listening = true; + maybeInitiateReplset(); maybeCallOnListen(); }