mongo/jstests/replsets/initiate_takes_stable_check...

117 lines
3.8 KiB
JavaScript

/**
* Tests that we are able to roll back immediately after replSetInitiate.
*
* @tags: [
* requires_persistence,
* multiversion_incompatible,
* ]
*/
import {ReplSetTest} from "jstests/libs/replsettest.js";
import {restartServerReplication, stopServerReplication} from "jstests/libs/write_concern_util.js";
const rst = new ReplSetTest({
name: jsTestName(),
nodes: [
{
setParameter: {
"failpoint.pauseCheckpointThread": tojson({mode: "alwaysOn"}),
// We will not be able to rebuild primary only services as those ultimately
// require the checkpointer to be running.
"failpoint.PrimaryOnlyServiceSkipRebuildingInstances": tojson({mode: "alwaysOn"}),
"logComponentVerbosity": tojson({replication: 3}),
},
rsConfig: {priority: 2},
},
{
rsConfig: {priority: 1},
},
{
rsConfig: {priority: 0},
},
],
useBridge: true,
});
rst.startSet();
const config = rst.getReplSetConfig();
// We have to initiate manually as RST adds nodes one-by-one, which can lead to the first
// node taking a stable checkpoint.
assert.commandWorked(rst.nodes[0].adminCommand({replSetInitiate: config}));
jsTestLog("Done initiating");
const node0 = rst.nodes[0];
const node1 = rst.nodes[1];
const node2 = rst.nodes[2];
const dbName = "testdb";
const collName = "testcoll";
// Make the first node the primary.
rst.stepUp(node0, {awaitReplicationBeforeStepUp: false});
const oldPrimary = rst.getPrimary();
assert.eq(node0, oldPrimary);
rst.awaitSecondaryNodes();
rst.awaitNodesAgreeOnConfigVersion();
rst.awaitReplication();
const oldPrimaryDB = oldPrimary.getDB(dbName);
const oldPrimaryColl = oldPrimaryDB.getCollection(collName);
jsTestLog("Stopping replication");
stopServerReplication(node1);
stopServerReplication(node2);
jsTestLog("Writing to old primary");
assert.commandWorked(oldPrimaryColl.insert({"old1": 1}, {writeConcern: {w: 1}}));
assert.commandWorked(oldPrimaryColl.insert({"old2": 2}, {writeConcern: {w: 1}}));
jsTestLog("Disconnecting old primary");
node0.disconnect(node1);
node0.disconnect(node2);
assert.commandWorked(oldPrimary.adminCommand({replSetStepDown: 10 * 60, force: true}));
rst.awaitSecondaryNodes(null, [rst.nodes[0]]);
jsTestLog("Electing new primary");
restartServerReplication(node1);
restartServerReplication(node2);
const newPrimary = rst.getPrimary();
const lastNode = newPrimary.host === node1.host ? node2 : node1;
jsTestLog("Writing to new primary " + newPrimary.host);
const newPrimaryDB = newPrimary.getDB(dbName);
const newPrimaryColl = newPrimaryDB.getCollection(collName);
assert.commandWorked(newPrimaryColl.insert({"new1": 1}, {writeConcern: {w: 1}}));
assert.commandWorked(newPrimaryColl.insert({"new2": 2}, {writeConcern: {w: 1}}));
rst.awaitReplication(undefined /* timeout */, undefined /* secondaryOpTimeType */, [lastNode]);
rst.awaitLastOpCommitted(undefined /* timeout */, [lastNode]);
jsTestLog("Reconnecting old primary");
const lastRBID = assert.commandWorked(node0.adminCommand("replSetGetRBID")).rbid;
node0.reconnect(node1);
node0.reconnect(node2);
rst.waitForState(rst.nodes[0], ReplSetTest.State.ROLLBACK);
// We take a stable checkpoint at the end of rollback so we need the checkpointer to be running.
jsTestLog("Reenabling checkpointer so rollback can complete");
assert.soonNoExcept(
function () {
assert.commandWorked(rst.nodes[0].adminCommand({configureFailPoint: "pauseCheckpointThread", mode: "off"}));
const rbid = assert.commandWorked(node0.adminCommand("replSetGetRBID")).rbid;
return rbid > lastRBID;
},
"rbid did not update",
ReplSetTest.kDefaultTimeoutMS,
);
rst.awaitSecondaryNodes(null, [rst.nodes[0]]);
jsTestLog("Done with test");
rst.stopSet();