Previously, mongos would not report writeConcernErrors for ordered writes that had writeErrors. Mongos now should report writeConcernErrors in the presence of writeErrors regardless of whether the batch is ordered or unordered.
84 lines
3.2 KiB
JavaScript
84 lines
3.2 KiB
JavaScript
/**
|
|
* This file tests that if a user initiates a write that becomes a noop either due to being a
|
|
* duplicate operation or due to errors relying on data reads, that we still wait for write concern.
|
|
* This is because we must wait for write concern on the write that made this a noop so that we can
|
|
* be sure it doesn't get rolled back if we acknowledge it.
|
|
*/
|
|
|
|
import {getNoopWriteCommands} from "jstests/libs/noop_write_commands.js";
|
|
import {assertWriteConcernError} from "jstests/libs/write_concern_util.js";
|
|
|
|
var name = 'noop_writes_wait_for_write_concern';
|
|
var replTest = new ReplSetTest({
|
|
name: name,
|
|
nodes: [{}, {rsConfig: {priority: 0}}, {rsConfig: {priority: 0}}],
|
|
});
|
|
replTest.startSet();
|
|
replTest.initiate();
|
|
// Stops node 1 so that all w:3 write concerns time out. We have 3 data bearing nodes so that
|
|
// 'dropDatabase' can satisfy its implicit writeConcern: majority but still time out from the
|
|
// explicit w:3 write concern.
|
|
replTest.stop(1);
|
|
|
|
var primary = replTest.getPrimary();
|
|
assert.eq(primary, replTest.nodes[0]);
|
|
var dbName = 'testDB';
|
|
var db = primary.getDB(dbName);
|
|
var collName = 'testColl';
|
|
var coll = db[collName];
|
|
const commands = getNoopWriteCommands(coll);
|
|
|
|
function dropTestCollection() {
|
|
coll.drop();
|
|
assert.eq(0, coll.find().itcount(), "test collection not empty");
|
|
}
|
|
|
|
function testCommandWithWriteConcern(cmd) {
|
|
// Provide a small wtimeout that we expect to time out.
|
|
cmd.req.writeConcern = {w: 3, wtimeout: 1000};
|
|
jsTest.log("Testing " + tojson(cmd.req));
|
|
|
|
// Don't run drop cmd on older versions. Starting in v7.0 drop returns OK on non-existent
|
|
// collections, instead of a NamespaceNotFound error.
|
|
if (cmd.req["drop"] !== undefined) {
|
|
const primaryShell = new Mongo(primary.host);
|
|
const primaryBinVersion = primaryShell.getDB("admin").serverStatus()["version"];
|
|
if (primaryBinVersion != MongoRunner.getBinVersionFor("latest")) {
|
|
jsTest.log(
|
|
"Skipping test: drop on non-existent collections in older versions returns an error.");
|
|
return;
|
|
}
|
|
}
|
|
|
|
dropTestCollection();
|
|
|
|
cmd.setupFunc();
|
|
|
|
// We run the command on a different connection. If the the command were run on the
|
|
// same connection, then the client last op for the noop write would be set by the setup
|
|
// operation. By using a fresh connection the client last op begins as null.
|
|
// This test explicitly tests that write concern for noop writes works when the
|
|
// client last op has not already been set by a duplicate operation.
|
|
var shell2 = new Mongo(primary.host);
|
|
|
|
// We check the error code of 'res' in the 'confirmFunc'.
|
|
var res = "bulkWrite" in cmd.req ? shell2.adminCommand(cmd.req)
|
|
: shell2.getDB(dbName).runCommand(cmd.req);
|
|
|
|
try {
|
|
// Tests that the command receives a write concern error. If we don't wait for write
|
|
// concern on noop writes then we won't get a write concern error.
|
|
assertWriteConcernError(res);
|
|
cmd.confirmFunc(res);
|
|
} catch (e) {
|
|
// Make sure that we print out the response.
|
|
printjson(res);
|
|
throw e;
|
|
}
|
|
}
|
|
|
|
commands.forEach(function(cmd) {
|
|
testCommandWithWriteConcern(cmd);
|
|
});
|
|
|
|
replTest.stopSet(); |