2014-11-05 11:49:27 -05:00
|
|
|
// Ensure writes do not prevent a node from Stepping down
|
|
|
|
|
// 1. Start up a 3 node set (1 arbiter).
|
2015-10-09 19:40:08 -04:00
|
|
|
// 2. Stop replication on the SECONDARY using a fail point.
|
2014-11-05 11:49:27 -05:00
|
|
|
// 3. Do one write and then spin up a second shell which asks the PRIMARY to StepDown.
|
2020-08-24 12:25:14 -04:00
|
|
|
// 4. Once StepDown has begun, try to do a write and ensure that it fails with NotWritablePrimary
|
2017-09-13 17:16:21 -04:00
|
|
|
// 5. Restart replication on the SECONDARY.
|
2014-11-05 11:49:27 -05:00
|
|
|
// 6. Wait for PRIMARY to StepDown.
|
|
|
|
|
|
2024-08-20 17:54:15 -04:00
|
|
|
import {ReplSetTest} from "jstests/libs/replsettest.js";
|
2017-09-13 17:16:21 -04:00
|
|
|
import {restartServerReplication, stopServerReplication} from "jstests/libs/write_concern_util.js";
|
|
|
|
|
|
2025-08-28 15:11:44 -04:00
|
|
|
let name = "stepDownWithLongWait";
|
|
|
|
|
let replSet = new ReplSetTest({name: name, nodes: 3});
|
|
|
|
|
let nodes = replSet.nodeList();
|
2014-11-05 11:49:27 -05:00
|
|
|
replSet.startSet();
|
2016-03-09 12:17:50 -05:00
|
|
|
replSet.initiate({
|
|
|
|
|
"_id": name,
|
|
|
|
|
"members": [
|
|
|
|
|
{"_id": 0, "host": nodes[0], "priority": 3},
|
|
|
|
|
{"_id": 1, "host": nodes[1]},
|
2025-08-21 10:17:44 -07:00
|
|
|
{"_id": 2, "host": nodes[2], "arbiterOnly": true},
|
|
|
|
|
],
|
2016-03-09 12:17:50 -05:00
|
|
|
});
|
2014-11-05 11:49:27 -05:00
|
|
|
|
2016-09-22 09:40:38 -04:00
|
|
|
replSet.waitForState(replSet.nodes[0], ReplSetTest.State.PRIMARY);
|
2025-08-28 15:11:44 -04:00
|
|
|
let primary = replSet.getPrimary();
|
2021-04-29 01:19:06 +00:00
|
|
|
// The default WC is majority and stopServerReplication will prevent satisfying any majority writes.
|
2025-08-21 10:17:44 -07:00
|
|
|
assert.commandWorked(
|
|
|
|
|
primary.adminCommand({setDefaultRWConcern: 1, defaultWriteConcern: {w: 1}, writeConcern: {w: "majority"}}),
|
|
|
|
|
);
|
2015-10-09 19:40:08 -04:00
|
|
|
|
2025-08-28 15:11:44 -04:00
|
|
|
let secondary = replSet.getSecondary();
|
2025-08-21 10:17:44 -07:00
|
|
|
jsTestLog("Disable replication on the SECONDARY " + secondary.host);
|
2017-09-13 17:16:21 -04:00
|
|
|
stopServerReplication(secondary);
|
2014-11-05 11:49:27 -05:00
|
|
|
|
|
|
|
|
jsTestLog("do a write then ask the PRIMARY to stepdown");
|
2025-08-28 15:11:44 -04:00
|
|
|
let options = {writeConcern: {w: 1, wtimeout: ReplSetTest.kDefaultTimeoutMS}};
|
2019-08-14 13:52:59 +00:00
|
|
|
assert.commandWorked(primary.getDB(name).foo.insert({x: 1}, options));
|
2017-09-13 17:16:21 -04:00
|
|
|
|
2025-08-28 15:11:44 -04:00
|
|
|
let stepDownCmd = function () {
|
2019-02-04 17:57:00 -05:00
|
|
|
assert.commandWorked(db.adminCommand({replSetStepDown: 60, secondaryCatchUpPeriodSecs: 60}));
|
2017-09-13 17:16:21 -04:00
|
|
|
};
|
2025-08-28 15:11:44 -04:00
|
|
|
let stepDowner = startParallelShell(stepDownCmd, primary.port);
|
2015-10-05 14:35:01 -04:00
|
|
|
|
2025-08-21 10:17:44 -07:00
|
|
|
assert.soon(function () {
|
2025-08-28 15:11:44 -04:00
|
|
|
let res = primary.getDB("admin").currentOp(true);
|
|
|
|
|
for (let entry in res.inprog) {
|
2025-08-21 10:17:44 -07:00
|
|
|
if (res.inprog[entry]["command"] && res.inprog[entry]["command"]["replSetStepDown"] === 60) {
|
2014-11-05 11:49:27 -05:00
|
|
|
return true;
|
|
|
|
|
}
|
2019-07-26 18:20:35 -04:00
|
|
|
}
|
2014-11-05 11:49:27 -05:00
|
|
|
printjson(res);
|
|
|
|
|
return false;
|
2017-09-13 17:16:21 -04:00
|
|
|
}, "No pending stepdown command found");
|
2014-11-05 11:49:27 -05:00
|
|
|
|
2020-08-24 12:25:14 -04:00
|
|
|
jsTestLog("Ensure that writes start failing with NotWritablePrimary errors");
|
2025-08-21 10:17:44 -07:00
|
|
|
assert.soonNoExcept(function () {
|
|
|
|
|
assert.commandFailedWithCode(primary.getDB(name).foo.insert({x: 2}), ErrorCodes.NotWritablePrimary);
|
2017-09-13 17:16:21 -04:00
|
|
|
return true;
|
|
|
|
|
});
|
|
|
|
|
|
2025-08-21 10:17:44 -07:00
|
|
|
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);
|
2014-11-05 11:49:27 -05:00
|
|
|
|
2025-08-21 10:17:44 -07:00
|
|
|
jsTestLog("Enable replication on the SECONDARY " + secondary.host);
|
2017-09-13 17:16:21 -04:00
|
|
|
restartServerReplication(secondary);
|
2014-11-05 11:49:27 -05:00
|
|
|
|
2015-10-09 19:40:08 -04:00
|
|
|
jsTestLog("Wait for PRIMARY " + primary.host + " to completely step down.");
|
2024-12-05 10:46:06 -08:00
|
|
|
replSet.awaitSecondaryNodes(null, [primary]);
|
2025-08-28 15:11:44 -04:00
|
|
|
let exitCode = stepDowner();
|
2015-06-23 22:22:52 -04:00
|
|
|
|
2015-10-09 19:40:08 -04:00
|
|
|
jsTestLog("Wait for SECONDARY " + secondary.host + " to become PRIMARY");
|
2017-09-13 17:16:21 -04:00
|
|
|
replSet.waitForState(secondary, ReplSetTest.State.PRIMARY);
|
2025-08-21 10:17:44 -07:00
|
|
|
replSet.stopSet();
|