/*
|
* Test linearizability of getMore on a cursor.
|
*/
|
(function() {
|
'use strict';
|
|
var num_nodes = 3;
|
var name = 'linearizable_read_concern';
|
var replTest = new ReplSetTest({name: name, nodes: num_nodes, useBridge: true});
|
var config = replTest.getReplSetConfig();
|
|
// Increased election timeout to avoid having the primary step down while we are
|
// testing linearizable functionality on an isolated primary.
|
config.settings = {electionTimeoutMillis: 20000};
|
|
replTest.startSet();
|
replTest.initiate(config);
|
replTest.awaitReplication();
|
var primary = replTest.getPrimary();
|
var secondaries = replTest.getSecondaries();
|
|
// Do a write on the original primary.
|
assert.writeOK(
|
primary.getDB("test").foo.insert({_id: 0, x: 0}, {"writeConcern": {"w": "majority"}}));
|
primary = replTest.getPrimary();
|
|
// Open a cursor on the original primary at 'linearizable' read concern.
|
let result = primary.getDB("test").runCommand(
|
{"find": "foo", filter: {_id: 0}, "readConcern": {level: "linearizable"}, batchSize: 0});
|
assert.commandWorked(result);
|
let cursorId = result.cursor.id;
|
|
jsTestLog(
|
"Setting up partitions such that the primary is isolated: [Secondary-Secondary] [Primary]");
|
secondaries[0].disconnect(primary);
|
secondaries[1].disconnect(primary);
|
|
jsTestLog("Step up a new primary, and wait until it can accept writes.");
|
assert.commandWorked(secondaries[0].adminCommand({replSetStepUp: 1}));
|
assert.soonNoExcept(function() {
|
return secondaries[0].adminCommand({isMaster: 1}).ismaster;
|
});
|
let newPrimary = secondaries[0];
|
jsTestLog("New node " + newPrimary + " should now be primary");
|
|
jsTestLog("Do a majority write to the new primary.");
|
assert.writeOK(newPrimary.getDB("test").foo.update(
|
{_id: 0}, {$set: {x: 1}}, {"writeConcern": {"w": "majority"}}));
|
|
jsTestLog("Do a linearizable read on the new primary.");
|
result = newPrimary.getDB("test").runCommand(
|
{"find": "foo", filter: {_id: 0}, "readConcern": {level: "linearizable"}, batchSize: 1});
|
assert.commandWorked(result);
|
// A linearizable read should return the effects of the most recent majority committed write.
|
assert.docEq([{_id: 0, x: 1}], result.cursor.firstBatch);
|
|
jsTestLog("Do a linearizable getMore read on the old primary.");
|
result =
|
primary.getDB("test").runCommand({"getMore": cursorId, collection: "foo", batchSize: 1});
|
assert.commandWorked(result);
|
// A linearizable read should return the effects of the most recent majority committed write
|
// (this should fail if getMores do not uphold linearizability guarantee correctly).
|
assert.docEq([{_id: 0, x: 1}], result.cursor.nextBatch);
|
|
// Re-connect and shut down.
|
secondaries[0].reconnect(primary);
|
secondaries[1].reconnect(primary);
|
replTest.stopSet();
|
}());
|