summaryrefslogtreecommitdiff
path: root/jstests/replsets/do_not_advance_commit_point_beyond_last_applied_term.js
diff options
context:
space:
mode:
Diffstat (limited to 'jstests/replsets/do_not_advance_commit_point_beyond_last_applied_term.js')
-rw-r--r--jstests/replsets/do_not_advance_commit_point_beyond_last_applied_term.js190
1 files changed, 96 insertions, 94 deletions
diff --git a/jstests/replsets/do_not_advance_commit_point_beyond_last_applied_term.js b/jstests/replsets/do_not_advance_commit_point_beyond_last_applied_term.js
index b5e67365eb4..35440fcb441 100644
--- a/jstests/replsets/do_not_advance_commit_point_beyond_last_applied_term.js
+++ b/jstests/replsets/do_not_advance_commit_point_beyond_last_applied_term.js
@@ -5,110 +5,112 @@
* @tags: [requires_majority_read_concern]
*/
(function() {
- "use strict";
+"use strict";
- load("jstests/libs/check_log.js");
- load("jstests/libs/write_concern_util.js"); // for [stop|restart]ServerReplication.
+load("jstests/libs/check_log.js");
+load("jstests/libs/write_concern_util.js"); // for [stop|restart]ServerReplication.
- const dbName = "test";
- const collName = "coll";
+const dbName = "test";
+const collName = "coll";
- // Set up a ReplSetTest where nodes only sync one oplog entry at a time.
- const rst = new ReplSetTest(
- {nodes: 5, useBridge: true, nodeOptions: {setParameter: "bgSyncOplogFetcherBatchSize=1"}});
- rst.startSet();
- const config = rst.getReplSetConfig();
- // Prevent elections.
- config.settings = {electionTimeoutMillis: 12 * 60 * 60 * 1000};
- rst.initiate(config);
+// Set up a ReplSetTest where nodes only sync one oplog entry at a time.
+const rst = new ReplSetTest(
+ {nodes: 5, useBridge: true, nodeOptions: {setParameter: "bgSyncOplogFetcherBatchSize=1"}});
+rst.startSet();
+const config = rst.getReplSetConfig();
+// Prevent elections.
+config.settings = {
+ electionTimeoutMillis: 12 * 60 * 60 * 1000
+};
+rst.initiate(config);
- const nodeA = rst.nodes[0];
- const nodeB = rst.nodes[1];
- const nodeC = rst.nodes[2];
- const nodeD = rst.nodes[3];
- const nodeE = rst.nodes[4];
+const nodeA = rst.nodes[0];
+const nodeB = rst.nodes[1];
+const nodeC = rst.nodes[2];
+const nodeD = rst.nodes[3];
+const nodeE = rst.nodes[4];
- jsTest.log("Node A is primary in term 1. Node E is delayed.");
- // A: [1]
- // B: [1]
- // C: [1]
- // D: [1]
- // E:
- assert.eq(nodeA, rst.getPrimary());
- nodeE.disconnect([nodeA, nodeB, nodeC, nodeD]);
- assert.commandWorked(nodeA.getDB(dbName)[collName].insert({term: 1}));
- rst.awaitReplication(undefined, undefined, [nodeB, nodeC, nodeD]);
+jsTest.log("Node A is primary in term 1. Node E is delayed.");
+// A: [1]
+// B: [1]
+// C: [1]
+// D: [1]
+// E:
+assert.eq(nodeA, rst.getPrimary());
+nodeE.disconnect([nodeA, nodeB, nodeC, nodeD]);
+assert.commandWorked(nodeA.getDB(dbName)[collName].insert({term: 1}));
+rst.awaitReplication(undefined, undefined, [nodeB, nodeC, nodeD]);
- jsTest.log("Node B steps up in term 2 and performs a write, which is not replicated.");
- // A: [1]
- // B: [1] [2]
- // C: [1]
- // D: [1]
- // E:
- stopServerReplication([nodeA, nodeC, nodeD]);
- assert.commandWorked(nodeB.adminCommand({replSetStepUp: 1}));
- rst.waitForState(nodeA, ReplSetTest.State.SECONDARY);
- assert.eq(nodeB, rst.getPrimary());
- assert.commandWorked(nodeB.getDB(dbName)[collName].insert({term: 2}));
+jsTest.log("Node B steps up in term 2 and performs a write, which is not replicated.");
+// A: [1]
+// B: [1] [2]
+// C: [1]
+// D: [1]
+// E:
+stopServerReplication([nodeA, nodeC, nodeD]);
+assert.commandWorked(nodeB.adminCommand({replSetStepUp: 1}));
+rst.waitForState(nodeA, ReplSetTest.State.SECONDARY);
+assert.eq(nodeB, rst.getPrimary());
+assert.commandWorked(nodeB.getDB(dbName)[collName].insert({term: 2}));
- jsTest.log("Node A steps up again in term 3 with votes from A, C, and D and commits a write.");
- // A: [1] [3]
- // B: [1] [2]
- // C: [1] [3]
- // D: [1] [3]
- // E:
- nodeB.disconnect([nodeA, nodeC, nodeD, nodeE]);
- assert.commandWorked(nodeA.adminCommand({replSetStepUp: 1}));
- restartServerReplication([nodeA, nodeC, nodeD]);
- assert.soon(() => {
- // We cannot use getPrimary() here because 2 nodes report they are primary.
- return assert.commandWorked(nodeA.adminCommand({ismaster: 1})).ismaster;
- });
- assert.commandWorked(
- nodeA.getDB(dbName)[collName].insert({term: 3}, {writeConcern: {w: "majority"}}));
- assert.eq(1, nodeC.getDB(dbName)[collName].find({term: 3}).itcount());
- assert.eq(1, nodeD.getDB(dbName)[collName].find({term: 3}).itcount());
+jsTest.log("Node A steps up again in term 3 with votes from A, C, and D and commits a write.");
+// A: [1] [3]
+// B: [1] [2]
+// C: [1] [3]
+// D: [1] [3]
+// E:
+nodeB.disconnect([nodeA, nodeC, nodeD, nodeE]);
+assert.commandWorked(nodeA.adminCommand({replSetStepUp: 1}));
+restartServerReplication([nodeA, nodeC, nodeD]);
+assert.soon(() => {
+ // We cannot use getPrimary() here because 2 nodes report they are primary.
+ return assert.commandWorked(nodeA.adminCommand({ismaster: 1})).ismaster;
+});
+assert.commandWorked(
+ nodeA.getDB(dbName)[collName].insert({term: 3}, {writeConcern: {w: "majority"}}));
+assert.eq(1, nodeC.getDB(dbName)[collName].find({term: 3}).itcount());
+assert.eq(1, nodeD.getDB(dbName)[collName].find({term: 3}).itcount());
- jsTest.log("Node E syncs from a majority node and learns the new commit point in term 3.");
- // A: [1] [3]
- // B: [1] [2]
- // C: [1] [3]
- // D: [1] [3]
- // E: [1]
- // The stopReplProducerOnDocument failpoint ensures that Node E stops replicating before
- // applying the document {msg: "new primary"}, which is the first document of term 3. This
- // depends on the oplog fetcher batch size being 1.
- assert.commandWorked(nodeE.adminCommand({
- configureFailPoint: "stopReplProducerOnDocument",
- mode: "alwaysOn",
- data: {document: {msg: "new primary"}}
- }));
- nodeE.reconnect([nodeA, nodeC, nodeD]);
- checkLog.contains(nodeE, "stopReplProducerOnDocument fail point is enabled.");
- assert.soon(() => {
- return 1 === nodeE.getDB(dbName)[collName].find({term: 1}).itcount();
- });
- assert.eq(0, nodeE.getDB(dbName)[collName].find({term: 3}).itcount());
+jsTest.log("Node E syncs from a majority node and learns the new commit point in term 3.");
+// A: [1] [3]
+// B: [1] [2]
+// C: [1] [3]
+// D: [1] [3]
+// E: [1]
+// The stopReplProducerOnDocument failpoint ensures that Node E stops replicating before
+// applying the document {msg: "new primary"}, which is the first document of term 3. This
+// depends on the oplog fetcher batch size being 1.
+assert.commandWorked(nodeE.adminCommand({
+ configureFailPoint: "stopReplProducerOnDocument",
+ mode: "alwaysOn",
+ data: {document: {msg: "new primary"}}
+}));
+nodeE.reconnect([nodeA, nodeC, nodeD]);
+checkLog.contains(nodeE, "stopReplProducerOnDocument fail point is enabled.");
+assert.soon(() => {
+ return 1 === nodeE.getDB(dbName)[collName].find({term: 1}).itcount();
+});
+assert.eq(0, nodeE.getDB(dbName)[collName].find({term: 3}).itcount());
- jsTest.log("Node E switches its sync source to B and replicates the stale branch of term 2.");
- nodeE.disconnect([nodeA, nodeC, nodeD]);
- nodeB.reconnect(nodeE);
- assert.commandWorked(
- nodeE.adminCommand({configureFailPoint: "stopReplProducerOnDocument", mode: "off"}));
- assert.soon(() => {
- return 1 === nodeE.getDB(dbName)[collName].find({term: 2}).itcount();
- });
+jsTest.log("Node E switches its sync source to B and replicates the stale branch of term 2.");
+nodeE.disconnect([nodeA, nodeC, nodeD]);
+nodeB.reconnect(nodeE);
+assert.commandWorked(
+ nodeE.adminCommand({configureFailPoint: "stopReplProducerOnDocument", mode: "off"}));
+assert.soon(() => {
+ return 1 === nodeE.getDB(dbName)[collName].find({term: 2}).itcount();
+});
- jsTest.log("Node E must not return the entry in term 2 as committed.");
- assert.eq(0, nodeE.getDB(dbName)[collName].find({term: 2}).readConcern("majority").itcount());
+jsTest.log("Node E must not return the entry in term 2 as committed.");
+assert.eq(0, nodeE.getDB(dbName)[collName].find({term: 2}).readConcern("majority").itcount());
- jsTest.log("Reconnect the set. Node E must roll back successfully.");
- nodeE.reconnect([nodeA, nodeC, nodeD]);
- nodeB.reconnect([nodeA, nodeC, nodeD]);
- rst.awaitReplication();
- assert.eq(1, nodeE.getDB(dbName)[collName].find({term: 1}).itcount());
- assert.eq(0, nodeE.getDB(dbName)[collName].find({term: 2}).itcount());
- assert.eq(1, nodeE.getDB(dbName)[collName].find({term: 3}).itcount());
+jsTest.log("Reconnect the set. Node E must roll back successfully.");
+nodeE.reconnect([nodeA, nodeC, nodeD]);
+nodeB.reconnect([nodeA, nodeC, nodeD]);
+rst.awaitReplication();
+assert.eq(1, nodeE.getDB(dbName)[collName].find({term: 1}).itcount());
+assert.eq(0, nodeE.getDB(dbName)[collName].find({term: 2}).itcount());
+assert.eq(1, nodeE.getDB(dbName)[collName].find({term: 3}).itcount());
- rst.stopSet();
+rst.stopSet();
}());