summaryrefslogtreecommitdiff
path: root/jstests/replsets/force_reconfig_skips_oplog_commitment.js
blob: 518fbba41ad285e80ab2af2f7a3c2274c00d4c88 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/**
 * Verify that a force replica set reconfig skips the oplog commitment check. The force reconfig
 * should succeed even though oplog entries committed in the previous config are not committed in
 * the current config.
 */

(function() {
"use strict";
load("jstests/libs/write_concern_util.js");
load("jstests/replsets/rslib.js");  // For reconnect.

const dbName = "test";
const collName = "coll";
// Make the secondary unelectable.
let rst = new ReplSetTest({nodes: [{}, {rsConfig: {priority: 0}}]});
rst.startSet();
rst.initiate();

const primary = rst.getPrimary();
const secondary = rst.getSecondary();
const coll = primary.getDB(dbName)[collName];

// This makes the test run faster.
assert.commandWorked(secondary.adminCommand(
    {configureFailPoint: 'setSmallOplogGetMoreMaxTimeMS', mode: 'alwaysOn'}));

// Create collection.
assert.commandWorked(coll.insert({}));
rst.awaitReplication();

// Stop replication on the secondary.
stopServerReplication(secondary);
// Avoid closing the connection when the secondary node transitions to REMOVED.
assert.commandWorked(secondary.adminCommand({hello: 1, hangUpOnStepDown: false}));

// Reconfig down to a 1 node replica set.
const origConfig = rst.getReplSetConfigFromNode();
let C1 = Object.assign({}, origConfig);
C1.members = C1.members.slice(0, 1);  // Remove the second node.
C1.version++;
assert.commandWorked(primary.adminCommand({replSetReconfig: C1}));

// Wait for the secondary node to realize it is REMOVED.
assert.soonNoExcept(function() {
    let res = secondary.adminCommand({replSetGetStatus: 1});
    assert.commandFailedWithCode(res, ErrorCodes.InvalidReplicaSetConfig);
    return true;
}, () => tojson(secondary.adminCommand({replSetGetStatus: 1})));

jsTestLog("Test that force reconfig skips oplog commitment.");
let C2 = Object.assign({}, origConfig);

jsTestLog("Do a write on primary and commit it in the current config.");
assert.commandWorked(coll.insert({x: 1}, {writeConcern: {w: "majority"}}));

jsTestLog("Reconfig to add the secondary back in.");

// As this force reconfig will skip the oplog commitment safety check,
// it should succeed even though the last committed op on C1 has not been committed on C2.
assert.commandWorked(primary.adminCommand({replSetReconfig: C2, force: true}));
const C3 = primary.getDB("local").system.replset.findOne();
// Run another force reconfig to verify the pre-condition check is also skipped
assert.commandWorked(primary.adminCommand({replSetReconfig: C3, force: true}));

restartServerReplication(secondary);
rst.awaitNodesAgreeOnConfigVersion();

rst.stopSet();
}());