125 lines
4.6 KiB
JavaScript
125 lines
4.6 KiB
JavaScript
/**
|
|
* Tests that the mongo shell doesn't attempt to retry its write operations after downgrading from
|
|
* 3.6 to 3.4.
|
|
*/
|
|
(function() {
|
|
"use strict";
|
|
|
|
load("jstests/libs/retryable_writes_util.js");
|
|
|
|
if (!RetryableWritesUtil.storageEngineSupportsRetryableWrites(jsTest.options().storageEngine)) {
|
|
jsTestLog("Retryable writes are not supported, skipping test");
|
|
return;
|
|
}
|
|
|
|
load("jstests/replsets/rslib.js");
|
|
|
|
const rst = new ReplSetTest({nodes: 1});
|
|
rst.startSet();
|
|
rst.initiate();
|
|
|
|
const primary = rst.getPrimary();
|
|
|
|
const db = primary.startSession({retryWrites: true}).getDatabase("test");
|
|
const coll = db.shell_retryable_writes_downgrade;
|
|
|
|
function testCommandCanBeRetried(func, {
|
|
expectedLogicalSessionId: expectedLogicalSessionId = true,
|
|
expectedTransactionNumber: expectedTransactionNumber = true
|
|
} = {}) {
|
|
const mongoRunCommandOriginal = Mongo.prototype.runCommand;
|
|
|
|
const sentinel = {};
|
|
let cmdObjSeen = sentinel;
|
|
|
|
Mongo.prototype.runCommand = function runCommandSpy(dbName, cmdObj, options) {
|
|
cmdObjSeen = cmdObj;
|
|
return mongoRunCommandOriginal.apply(this, arguments);
|
|
};
|
|
|
|
try {
|
|
assert.doesNotThrow(func);
|
|
} finally {
|
|
Mongo.prototype.runCommand = mongoRunCommandOriginal;
|
|
}
|
|
|
|
if (cmdObjSeen === sentinel) {
|
|
throw new Error("Mongo.prototype.runCommand() was never called: " + func.toString());
|
|
}
|
|
|
|
let cmdName = Object.keys(cmdObjSeen)[0];
|
|
|
|
// If the command is in a wrapped form, then we look for the actual command object inside
|
|
// the query/$query object.
|
|
if (cmdName === "query" || cmdName === "$query") {
|
|
cmdObjSeen = cmdObjSeen[cmdName];
|
|
cmdName = Object.keys(cmdObjSeen)[0];
|
|
}
|
|
|
|
if (expectedLogicalSessionId) {
|
|
assert(cmdObjSeen.hasOwnProperty("lsid"),
|
|
"Expected operation " + tojson(cmdObjSeen) + " to have a logical session id: " +
|
|
func.toString());
|
|
} else {
|
|
assert(!cmdObjSeen.hasOwnProperty("lsid"),
|
|
"Expected operation " + tojson(cmdObjSeen) +
|
|
" to not have a logical session id: " + func.toString());
|
|
}
|
|
|
|
if (expectedTransactionNumber) {
|
|
assert(cmdObjSeen.hasOwnProperty("txnNumber"),
|
|
"Expected operation " + tojson(cmdObjSeen) +
|
|
" to be assigned a transaction number since it can be retried: " +
|
|
func.toString());
|
|
} else {
|
|
assert(!cmdObjSeen.hasOwnProperty("txnNumber"),
|
|
"Expected operation " + tojson(cmdObjSeen) +
|
|
" to not be assigned a transaction number since it cannot be retried: " +
|
|
func.toString());
|
|
}
|
|
}
|
|
|
|
testCommandCanBeRetried(function() {
|
|
assert.writeOK(coll.insert({_id: "while fCV=3.6"}));
|
|
});
|
|
|
|
assert.commandWorked(db.adminCommand({setFeatureCompatibilityVersion: "3.4"}));
|
|
|
|
// The server errors on lsid and txnNumber while in featureCompatibilityVersion=3.4.
|
|
testCommandCanBeRetried(function() {
|
|
assert.writeError(coll.insert({_id: "while fCV=3.4"}));
|
|
});
|
|
|
|
rst.restart(primary, {binVersion: "3.4"});
|
|
rst.waitForMaster();
|
|
|
|
assert(db.getSession().getOptions().shouldRetryWrites(),
|
|
"Re-establishing the connection shouldn't change the state of the SessionOptions");
|
|
|
|
// After downgrading to MongoDB 3.4, the mongo shell shouldn't attempt to automatically retry
|
|
// write operations.
|
|
assert.throws(function() {
|
|
coll.insert({_id: "while in binVersion=3.4 and disconnected"});
|
|
});
|
|
|
|
// After downgrading to MongoDB 3.4, the mongo shell shouldn't inject an lsid or assign a
|
|
// transaction number to its write requests.
|
|
testCommandCanBeRetried(function() {
|
|
assert.writeOK(coll.insert({_id: "while binVersion=3.4 and reconnected"}));
|
|
}, {expectedLogicalSessionId: false, expectedTransactionNumber: false});
|
|
|
|
rst.restart(primary, {binVersion: "latest", noReplSet: true});
|
|
rst.waitForMaster();
|
|
reconnect(primary);
|
|
|
|
// When upgrading to MongoDB 3.6 but running as a stand-alone server, the mongo shell should
|
|
// still assign a transaction number to its write requests (per the Driver's specification).
|
|
testCommandCanBeRetried(function() {
|
|
assert.writeError(
|
|
coll.insert({_id: "while binVersion=3.6 as stand-alone and reconnected"}));
|
|
});
|
|
|
|
db.getSession().endSession();
|
|
rst.stopSet();
|
|
})();
|