85 lines
3.3 KiB
JavaScript
85 lines
3.3 KiB
JavaScript
// Ensure stepDown operations that are waiting for replication can be interrupted with killOp()
|
|
// 1. Start up a 3 node set (1 arbiter).
|
|
// 2. Stop replication on the SECONDARY using a fail point.
|
|
// 3. Do one write and then spin up a second shell which asks the PRIMARY to StepDown.
|
|
// 4. Once StepDown has begun, attempt to do writes and confirm that they fail with
|
|
// NotWritablePrimary.
|
|
// 5. Kill the stepDown operation.
|
|
// 6. Writes should become allowed again and the primary should stay primary.
|
|
|
|
import {ReplSetTest} from "jstests/libs/replsettest.js";
|
|
import {restartServerReplication, stopServerReplication} from "jstests/libs/write_concern_util.js";
|
|
|
|
var name = "interruptStepDown";
|
|
var replSet = new ReplSetTest({name: name, nodes: 3});
|
|
var nodes = replSet.nodeList();
|
|
replSet.startSet();
|
|
replSet.initiate({
|
|
"_id": name,
|
|
"members": [
|
|
{"_id": 0, "host": nodes[0]},
|
|
{"_id": 1, "host": nodes[1], "priority": 0},
|
|
{"_id": 2, "host": nodes[2], "arbiterOnly": true}
|
|
]
|
|
});
|
|
|
|
replSet.waitForState(replSet.nodes[0], ReplSetTest.State.PRIMARY);
|
|
// The default WC is majority and stopServerReplication will prevent satisfying any majority writes.
|
|
assert.commandWorked(replSet.getPrimary().adminCommand(
|
|
{setDefaultRWConcern: 1, defaultWriteConcern: {w: 1}, writeConcern: {w: "majority"}}));
|
|
replSet.awaitReplication();
|
|
|
|
var secondary = replSet.getSecondary();
|
|
jsTestLog('Disable replication on the SECONDARY ' + secondary.host);
|
|
stopServerReplication(secondary);
|
|
|
|
var primary = replSet.getPrimary();
|
|
assert.eq(primary.host, nodes[0], "primary assumed to be node 0");
|
|
|
|
// do a write then ask the PRIMARY to stepdown
|
|
jsTestLog("Initiating stepdown");
|
|
assert.commandWorked(primary.getDB(name).foo.insert(
|
|
{myDoc: true, x: 1}, {writeConcern: {w: 1, wtimeout: ReplSetTest.kDefaultTimeoutMS}}));
|
|
var stepDownCmd = function() {
|
|
var res =
|
|
db.getSiblingDB('admin').runCommand({replSetStepDown: 60, secondaryCatchUpPeriodSecs: 60});
|
|
assert.commandFailedWithCode(res, 11601 /*interrupted*/);
|
|
};
|
|
var stepDowner = startParallelShell(stepDownCmd, primary.port);
|
|
var stepDownOpID = -1;
|
|
|
|
jsTestLog("Looking for stepdown in currentOp() output");
|
|
assert.soon(function() {
|
|
var res = primary.getDB('admin').currentOp(true);
|
|
for (var index in res.inprog) {
|
|
var entry = res.inprog[index];
|
|
if (entry["command"] && entry["command"]["replSetStepDown"] === 60) {
|
|
stepDownOpID = entry.opid;
|
|
return true;
|
|
}
|
|
}
|
|
printjson(res);
|
|
return false;
|
|
}, "No pending stepdown command found");
|
|
|
|
jsTestLog("Ensure that writes start failing with NotWritablePrimary errors");
|
|
assert.soonNoExcept(function() {
|
|
assert.commandFailedWithCode(primary.getDB(name).foo.insert({x: 2}),
|
|
ErrorCodes.NotWritablePrimary);
|
|
return true;
|
|
});
|
|
|
|
jsTestLog("Ensure that even though writes are failing with NotWritablePrimary, we still report " +
|
|
"ourselves as PRIMARY");
|
|
assert.eq(ReplSetTest.State.PRIMARY, primary.adminCommand('replSetGetStatus').myState);
|
|
|
|
// kill the stepDown and ensure that that unblocks writes to the db
|
|
jsTestLog("Killing stepdown");
|
|
primary.getDB('admin').killOp(stepDownOpID);
|
|
|
|
var exitCode = stepDowner();
|
|
assert.eq(0, exitCode);
|
|
|
|
assert.commandWorked(primary.getDB(name).foo.remove({}));
|
|
restartServerReplication(secondary);
|
|
replSet.stopSet(); |