Merge pull request #7840 from meteor/reconfigure-mongo-when-port-differs

Reconfigure Mongo replica set when --port differs
This commit is contained in:
Ben Newman
2016-09-29 16:56:36 -04:00
committed by GitHub
13 changed files with 254 additions and 93 deletions

View File

@@ -482,15 +482,15 @@ var launchMongo = function (options) {
proc = spawnMongod(mongod_path, port, dbPath, replSetName);
subHandles.push({
stop: function () {
if (proc) {
proc.removeListener('exit', procExitHandler);
proc.kill('SIGINT');
proc = null;
}
function stop() {
if (proc) {
proc.removeListener('exit', procExitHandler);
proc.kill('SIGINT');
proc = null;
}
});
}
require("../tool-env/cleanup.js").onExit(stop);
subHandles.push({ stop });
var procExitHandler = fiberHelpers.bindEnvironment(function (code, signal) {
// Defang subHandle.stop().
@@ -532,7 +532,8 @@ var launchMongo = function (options) {
var stdoutOnData = fiberHelpers.bindEnvironment(function (data) {
// note: don't use "else ifs" in this, because 'data' can have multiple
// lines
if (/\[initandlisten\] Did not find local replica set configuration document at startup/.test(data)) {
if (/\[initandlisten\] Did not find local replica set configuration document at startup/.test(data) ||
/\[ReplicationExecutor\] Locally stored replica set configuration does not have a valid entry for the current node/.test(data)) {
replSetReadyToBeInitiated = true;
maybeReadyToTalk();
}
@@ -596,10 +597,25 @@ var launchMongo = function (options) {
if (stopped) {
return;
}
var configuration = {
_id: replSetName,
version: 1,
members: [{_id: 0, host: '127.0.0.1:' + options.port, priority: 100}]
};
try {
const config = yieldingMethod(db.admin(), "command", {
replSetGetConfig: 1,
}).config;
// If a replication set configuration already exists, it's
// important that the new version number is greater than the old.
if (config && _.has(config, "version")) {
configuration.version = config.version + 1;
}
} catch (e) {}
if (options.multiple) {
// Add two more members: one of which should start as secondary but
// could in theory become primary, and one of which can never be
@@ -613,10 +629,16 @@ var launchMongo = function (options) {
}
try {
var initiateResult = yieldingMethod(
db.admin(), 'command', {replSetInitiate: configuration});
yieldingMethod(db.admin(), 'command', {
replSetInitiate: configuration,
});
} catch (e) {
if (e.message !== 'already initialized') {
if (e.message === 'already initialized') {
yieldingMethod(db.admin(), 'command', {
replSetReconfig: configuration,
force: true,
});
} else {
throw Error("rs.initiate error: " + e.message);
}
}

View File

@@ -0,0 +1,15 @@
# This file contains information which helps Meteor properly upgrade your
# app when you run 'meteor update'. You should check it into version control
# with your project.
notices-for-0.9.0
notices-for-0.9.1
0.9.4-platform-file
notices-for-facebook-graph-api-2
1.2.0-standard-minifiers-package
1.2.0-meteor-platform-split
1.2.0-cordova-changes
1.2.0-breaking-changes
1.3.0-split-minifiers-package
1.4.0-remove-old-dev-bundle-link
1.4.1-add-shell-server-package

View File

@@ -0,0 +1 @@
local

View File

@@ -0,0 +1,7 @@
# This file contains a token that is unique to your project.
# Check it into your repository along with the rest of this directory.
# It can be used for purposes such as:
# - ensuring you don't accidentally deploy one app on top of another
# - providing package authors with aggregated statistics
fgbyyt1b3uxw5u734ug

View File

@@ -0,0 +1,12 @@
# Meteor packages used by this project, one per line.
# Check this file (and the other files in this directory) into your repository.
#
# 'meteor add' and 'meteor remove' will edit this file for you,
# but you can also edit it by hand.
meteor-base # Packages every Meteor app needs to have
mongo # The database Meteor supports right now
ecmascript # Enable ECMAScript2015+ syntax in app code
shell-server # Server-side component of the `meteor shell` command

View File

@@ -0,0 +1,2 @@
server
browser

View File

@@ -0,0 +1 @@
none

View File

@@ -0,0 +1,54 @@
allow-deny@1.0.5
autoupdate@1.3.11
babel-compiler@6.9.2-beta.5
babel-runtime@0.1.12-beta.5
base64@1.0.9
binary-heap@1.0.9
blaze@2.1.8
blaze-tools@1.0.9
boilerplate-generator@1.0.10
callback-hook@1.0.9
check@1.2.3
ddp@1.2.5
ddp-client@1.3.2-beta.5
ddp-common@1.2.6
ddp-server@1.3.11-beta.5
deps@1.0.12
diff-sequence@1.0.6
ecmascript@0.5.9-beta.5
ecmascript-runtime@0.3.15-beta.5
ejson@1.0.12
geojson-utils@1.0.9
hot-code-push@1.0.4
html-tools@1.0.10
htmljs@1.0.10
http@1.2.10-beta.5
id-map@1.0.8
jquery@1.11.9
livedata@1.0.18
logging@1.1.16-beta.5
meteor@1.2.18-beta.5
meteor-base@1.0.4
minimongo@1.0.17
modules@0.7.7-beta.5
modules-runtime@0.7.7-beta.5
mongo@1.1.13-beta.5
mongo-id@1.0.5
npm-mongo@1.5.51-beta.5
observe-sequence@1.0.12
ordered-dict@1.0.8
promise@0.8.8-beta.5
random@1.0.10
reactive-var@1.0.10
reload@1.1.10
retry@1.0.8
routepolicy@1.0.11
shell-server@0.2.1
spacebars@1.0.12
spacebars-compiler@1.0.12
tracker@1.1.0
ui@1.0.11
underscore@1.0.9
url@1.0.10
webapp@1.3.12-beta.5
webapp-hashing@1.0.9

View File

@@ -0,0 +1,18 @@
import { Mongo } from 'meteor/mongo';
const collection = new Mongo.Collection("sanity");
Meteor.startup(() => {
let doc = collection.findOne();
if (! doc) {
collection.insert({ count: 0 });
doc = collection.findOne();
}
collection.update(doc._id, {
$inc: { count: 1 }
});
console.log("count: " + collection.findOne().count);
});

View File

@@ -56,3 +56,32 @@ selftest.define("meteor mongo", function () {
selftest.define("meteor mongo in unicode dir", function () {
testMeteorMongo('asdf\u0442asdf');
});
selftest.define("mongo with multiple --port numbers (#7563)", function () {
var s = new Sandbox();
s.createApp("mongo-multiple-ports", "mongo-sanity");
s.cd("mongo-multiple-ports");
function check(args, matches) {
const run = s.run(...args);
run.waitSecs(30);
matches.forEach(m => {
run.waitSecs(10);
run.match(m);
});
run.stop();
}
// Make absolutely sure we're creating the database for the first time.
check(["reset"], ["Project reset."]);
let count = 0;
function next() {
return ["Started MongoDB", "count: " + (++count)];
}
check(["run"], next());
check(["--port", "4321"], next());
check(["--port", "4123"], next());
check([], next());
});

View File

@@ -50,96 +50,95 @@ var runTest = function () {
catalog.official.initialize();
console.log("Bundle app with public/ directory");
assert.doesNotThrow(function () {
var projectContext = makeProjectContext("app-with-public");
var tmpOutputDir = tmpDir();
var result = bundler.bundle({
projectContext: projectContext,
outputPath: tmpOutputDir
});
var clientManifest = JSON.parse(
files.readFile(
files.pathJoin(tmpOutputDir, "programs", "web.browser", "program.json")
)
);
var projectContext = makeProjectContext("app-with-public");
var tmpOutputDir = tmpDir();
var testCases = [["/test.txt", "Test\n"],
["/nested/nested.txt", "Nested\n"]];
_.each(testCases, function (file) {
var manifestItem = _.find(clientManifest.manifest, function (m) {
return m.url === file[0];
});
assert(manifestItem);
var diskPath = files.pathJoin(tmpOutputDir, "programs", "web.browser",
manifestItem.path);
assert(files.exists(diskPath));
assert.strictEqual(files.readFile(diskPath, "utf8"), file[1]);
var result = bundler.bundle({
projectContext: projectContext,
outputPath: tmpOutputDir
});
var clientManifest = JSON.parse(
files.readFile(
files.pathJoin(tmpOutputDir, "programs", "web.browser", "program.json")
)
);
var testCases = [["/test.txt", "Test\n"],
["/nested/nested.txt", "Nested\n"]];
_.each(testCases, function (file) {
var manifestItem = _.find(clientManifest.manifest, function (m) {
return m.url === file[0];
});
assert(manifestItem);
var diskPath = files.pathJoin(tmpOutputDir, "programs", "web.browser",
manifestItem.path);
assert(files.exists(diskPath));
assert.strictEqual(files.readFile(diskPath, "utf8"), file[1]);
});
console.log("Bundle app with private/ directory and package asset");
assert.doesNotThrow(function () {
var projectContext = makeProjectContext("app-with-private");
var tmpOutputDir = tmpDir();
var projectContext = makeProjectContext("app-with-private");
var tmpOutputDir = tmpDir();
var result = bundler.bundle({
projectContext: projectContext,
outputPath: tmpOutputDir
});
var serverManifest = JSON.parse(
files.readFile(
files.pathJoin(tmpOutputDir, "programs", "server",
"program.json")
)
);
var testTxtPath;
var nestedTxtPath;
var packageTxtPath;
var unregisteredExtensionPath;
_.each(serverManifest.load, function (item) {
if (item.path === "packages/test-package.js") {
packageTxtPath = files.pathJoin(
tmpOutputDir, "programs", "server", item.assets['test-package.txt']);
unregisteredExtensionPath = files.pathJoin(
tmpOutputDir, "programs", "server", item.assets["test.notregistered"]);
}
if (item.path === "app/test.js") {
testTxtPath = files.pathJoin(
tmpOutputDir, "programs", "server", item.assets['test.txt']);
nestedTxtPath = files.pathJoin(
tmpOutputDir, "programs", "server", item.assets["nested/test.txt"]);
}
});
// check that the files are where the manifest says they are
assert.strictEqual(result.errors, false, result.errors && result.errors[0]);
assert(files.exists(testTxtPath));
assert(files.exists(nestedTxtPath));
assert(files.exists(packageTxtPath));
assert(files.exists(unregisteredExtensionPath));
assert.strictEqual(files.readFile(testTxtPath, "utf8"), "Test\n");
assert.strictEqual(files.readFile(nestedTxtPath, "utf8"), "Nested\n");
assert.strictEqual(files.readFile(packageTxtPath, "utf8"), "Package\n");
assert.strictEqual(files.readFile(unregisteredExtensionPath, "utf8"),
"No extension handler\n");
// Run the app to check that Assets.getText/Binary do the right things.
var meteorToolPath = files.convertToOSPath(process.env.METEOR_TOOL_PATH);
var fut = new Future();
require('child_process').execFile(
meteorToolPath,
// use a non-default port so we don't fail if someone is running an app
// now
["--once", "--port", "4123"], {
cwd: files.convertToOSPath(projectContext.projectDir),
stdio: 'inherit'
},
fut.resolver()
);
fut.wait(); // would throw if command failed
var result = bundler.bundle({
projectContext: projectContext,
outputPath: tmpOutputDir
});
var serverManifest = JSON.parse(
files.readFile(
files.pathJoin(tmpOutputDir, "programs", "server",
"program.json")
)
);
var testTxtPath;
var nestedTxtPath;
var packageTxtPath;
var unregisteredExtensionPath;
_.each(serverManifest.load, function (item) {
if (item.path === "packages/test-package.js") {
packageTxtPath = files.pathJoin(
tmpOutputDir, "programs", "server", item.assets['test-package.txt']);
unregisteredExtensionPath = files.pathJoin(
tmpOutputDir, "programs", "server", item.assets["test.notregistered"]);
}
if (item.path === "app/main.js") {
testTxtPath = files.pathJoin(
tmpOutputDir, "programs", "server", item.assets['test.txt']);
nestedTxtPath = files.pathJoin(
tmpOutputDir, "programs", "server", item.assets["nested/test.txt"]);
}
});
// check that the files are where the manifest says they are
assert.strictEqual(result.errors, false, result.errors && result.errors[0]);
assert(files.exists(testTxtPath));
assert(files.exists(nestedTxtPath));
assert(files.exists(packageTxtPath));
assert(files.exists(unregisteredExtensionPath));
assert.strictEqual(files.readFile(testTxtPath, "utf8"), "Test\n");
assert.strictEqual(files.readFile(nestedTxtPath, "utf8"), "Nested\n");
assert.strictEqual(files.readFile(packageTxtPath, "utf8"), "Package\n");
assert.strictEqual(files.readFile(unregisteredExtensionPath, "utf8"),
"No extension handler\n");
// Run the app to check that Assets.getText/Binary do the right things.
var meteorToolPath = files.convertToOSPath(process.env.METEOR_TOOL_PATH);
var fut = new Future();
require('child_process').execFile(
meteorToolPath,
// use a non-default port so we don't fail if someone is running an app
// now
["--once", "--port", "4123"], {
cwd: files.convertToOSPath(projectContext.projectDir),
stdio: 'inherit'
},
fut.resolver()
);
fut.wait(); // would throw if command failed
};
var Fiber = require('fibers');

View File

@@ -106,6 +106,7 @@ try {
run.match('s.json: parse error reading settings file');
run.match('Waiting for file change');
s.write('s.json', '{}');
run.waitSecs(15);
run.match('App running at');
run.stop();