mongo/jstests/replsets/rollback_during_step_up.js

72 lines
2.3 KiB
JavaScript

/**
* Tests that step-up to become a primary during rollback won't crash the server with
* OplogOutOfOrder error after becoming a secondary again.
* Exercises the fix for SERVER-61977.
* @tags: [uses_transactions]
*/
(function() {
"use strict";
load("jstests/libs/fail_point_util.js");
load("jstests/libs/write_concern_util.js");
const rst = new ReplSetTest({
name: jsTestName(),
nodes: 3,
settings: {chainingAllowed: false, catchUpTimeoutMillis: 0},
useBridge: true
});
rst.startSet();
rst.initiateWithHighElectionTimeout();
const node0 = rst.getPrimary();
const node1 = rst.getSecondaries()[0];
const node2 = rst.getSecondaries()[1];
const testDB = node0.getDB('test');
const collName = jsTestName();
const coll = testDB[collName];
assert.commandWorked(testDB.createCollection(coll.getName()));
rst.awaitReplication();
stopServerReplication([node1, node2]);
// Add a non replicated write to the node0 to be rolled back later.
assert.commandWorked(coll.insert({_id: "write 1"}, {writeConcern: {w: 1}}));
let rollbackFp = configureFailPoint(node0, "rollbackHangBeforeTransitioningToRollback");
rst.stepUp(node2, {awaitReplicationBeforeStepUp: false});
// When node0 starts syncing from the node2, it will rollback the write that didn't get replicated.
rollbackFp.wait();
// Step-up node0 while it is hung at rollback.
rst.stepUp(node0, {awaitReplicationBeforeStepUp: false});
// Rollback will fail because we do not allow transitioning to follower mode from node0.
rollbackFp.off();
// Wait for node0 to step-up to avoid InterrupetedDueToReplStateChange errors in the inserts below.
restartServerReplication([node1, node2]);
rst.awaitNodesAgreeOnPrimary(rst.kDefaultTimeoutMS, rst.nodes, node0);
rst.awaitReplication();
// Advance the lastApplied on node0.
assert.commandWorked(coll.insert({_id: "write 2"}));
assert.commandWorked(coll.insert({_id: "write 3"}));
rst.awaitReplication();
// When node0 stepped down it will start syncing again from node2, and it shouldn't crash trying to
// apply entries older than the lastApplied.
rst.stepUp(node2);
rst.awaitNodesAgreeOnPrimary(rst.kDefaultTimeoutMS, rst.nodes, node2);
rst.awaitReplication();
// Verify node0 can replicate new writes.
assert.commandWorked(node2.getDB('test')[collName].insert({_id: "write 4"}));
rst.awaitReplication();
rst.stopSet();
})();