Skip to content

Commit

Permalink
SERVER-80363 server default writeConcern is not honored when wtimeout…
Browse files Browse the repository at this point in the history
… is set
  • Loading branch information
moustafamaher authored and Evergreen Agent committed Nov 21, 2023
1 parent e1298b7 commit 8ecb0d8
Show file tree
Hide file tree
Showing 20 changed files with 630 additions and 222 deletions.
163 changes: 83 additions & 80 deletions jstests/noPassthrough/server_write_concern_metrics.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// Tests writeConcern metrics in the serverStatus output.
// Tests writeConcern metrics in the serverStatus output for a replica set.
// @tags: [
// requires_persistence,
// requires_replication,
// ]
// Verifies that the server status response has the fields that we expect.
function verifyServerStatusFields(serverStatusResponse) {
export function verifyServerStatusFields(serverStatusResponse) {
assert(serverStatusResponse.hasOwnProperty("opWriteConcernCounters"),
"Expected the serverStatus response to have a 'opWriteConcernCounters' field\n" +
tojson(serverStatusResponse));
Expand All @@ -21,7 +21,7 @@ function verifyServerStatusFields(serverStatusResponse) {

// Verifies that the given path of the server status response is incremented in the way we
// expect, and no other changes occurred. This function modifies its inputs.
function verifyServerStatusChange(initialStats, newStats, paths, expectedIncrement) {
export function verifyServerStatusChange(initialStats, newStats, paths, expectedIncrement) {
paths.forEach(path => {
// Traverse to the parent of the changed element.
let pathComponents = path.split(".");
Expand Down Expand Up @@ -66,6 +66,16 @@ function verifyServerStatusChange(initialStats, newStats, paths, expectedIncreme
", initialStats: " + tojson(initialStats) + ", newStats: " + tojson(newStats));
}

// Generate commands that will be using default write concern.
export function generateCmdsWithNoWCProvided(cmd) {
return [
cmd,
// Missing 'w' field will be filled with default write concern.
Object.assign(Object.assign({}, cmd), {writeConcern: {j: true}}),
Object.assign(Object.assign({}, cmd), {writeConcern: {wtimeout: 2000}})
];
}

let rst;
let primary;
let secondary;
Expand Down Expand Up @@ -104,23 +114,28 @@ function resetCollection(setupCommand) {
}

function testWriteConcernMetrics(cmd, opName, inc, isPSASet, setupCommand) {
jsTestLog("Testing " + opName + " - IsPSA: " + isPSASet);
initializeReplicaSet(isPSASet);

// Run command with no writeConcern and no CWWC set.
resetCollection(setupCommand);
let serverStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1}));
verifyServerStatusFields(serverStatus);
assert.commandWorked(testDB.runCommand(cmd));
let newStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1}));
verifyServerStatusChange(serverStatus.opWriteConcernCounters,
newStatus.opWriteConcernCounters,
[
opName +
(isPSASet ? ".noneInfo.implicitDefault.wnum.1"
: ".noneInfo.implicitDefault.wmajority"),
opName + ".none"
],
inc);
const cmdsWithNoWCProvided = generateCmdsWithNoWCProvided(cmd);
let serverStatus, newStatus;
cmdsWithNoWCProvided.forEach(cmd => {
serverStatus = assert.commandWorked(primary.adminCommand({serverStatus: 1}));
verifyServerStatusFields(serverStatus);
assert.commandWorked(testDB.runCommand(cmd));
newStatus = assert.commandWorked(primary.adminCommand({serverStatus: 1}));
verifyServerStatusChange(serverStatus.opWriteConcernCounters,
newStatus.opWriteConcernCounters,
[
opName +
(isPSASet ? ".noneInfo.implicitDefault.wnum.1"
: ".noneInfo.implicitDefault.wmajority"),
opName + ".none"
],
inc);
});

// Run command with no writeConcern with CWWC set to majority.
resetCollection(setupCommand);
Expand All @@ -129,40 +144,31 @@ function testWriteConcernMetrics(cmd, opName, inc, isPSASet, setupCommand) {
defaultWriteConcern: {w: "majority"},
writeConcern: {w: "majority"}
}));
serverStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1}));
verifyServerStatusFields(serverStatus);
assert.commandWorked(testDB.runCommand(cmd));
newStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1}));
verifyServerStatusChange(serverStatus.opWriteConcernCounters,
newStatus.opWriteConcernCounters,
[opName + ".noneInfo.CWWC.wmajority", opName + ".none"],
inc);
cmdsWithNoWCProvided.forEach(cmd => {
serverStatus = assert.commandWorked(primary.adminCommand({serverStatus: 1}));
verifyServerStatusFields(serverStatus);
assert.commandWorked(testDB.runCommand(cmd));
newStatus = assert.commandWorked(primary.adminCommand({serverStatus: 1}));
verifyServerStatusChange(serverStatus.opWriteConcernCounters,
newStatus.opWriteConcernCounters,
[opName + ".noneInfo.CWWC.wmajority", opName + ".none"],
inc);
});

// Run command with no writeConcern with CWWC set to w:1.
resetCollection(setupCommand);
assert.commandWorked(primary.adminCommand(
{setDefaultRWConcern: 1, defaultWriteConcern: {w: 1}, writeConcern: {w: "majority"}}));
serverStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1}));
verifyServerStatusFields(serverStatus);
assert.commandWorked(testDB.runCommand(cmd));
newStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1}));
verifyServerStatusChange(serverStatus.opWriteConcernCounters,
newStatus.opWriteConcernCounters,
[opName + ".noneInfo.CWWC.wnum.1", opName + ".none"],
inc);

// Run command with no writeConcern and with CWWC set to j:true.
resetCollection(setupCommand);
assert.commandWorked(primary.adminCommand(
{setDefaultRWConcern: 1, defaultWriteConcern: {j: true}, writeConcern: {w: "majority"}}));
serverStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1}));
verifyServerStatusFields(serverStatus);
assert.commandWorked(testDB.runCommand(cmd));
newStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1}));
verifyServerStatusChange(serverStatus.opWriteConcernCounters,
newStatus.opWriteConcernCounters,
[opName + ".noneInfo.CWWC.wnum.1", opName + ".none"],
inc);
cmdsWithNoWCProvided.forEach(cmd => {
serverStatus = assert.commandWorked(primary.adminCommand({serverStatus: 1}));
verifyServerStatusFields(serverStatus);
assert.commandWorked(testDB.runCommand(cmd));
newStatus = assert.commandWorked(primary.adminCommand({serverStatus: 1}));
verifyServerStatusChange(serverStatus.opWriteConcernCounters,
newStatus.opWriteConcernCounters,
[opName + ".noneInfo.CWWC.wnum.1", opName + ".none"],
inc);
});

// Run command with no writeConcern and with CWWC set with (w: "myTag").
resetCollection(setupCommand);
Expand All @@ -171,82 +177,79 @@ function testWriteConcernMetrics(cmd, opName, inc, isPSASet, setupCommand) {
defaultWriteConcern: {w: "myTag"},
writeConcern: {w: "majority"}
}));
serverStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1}));
verifyServerStatusFields(serverStatus);
assert.commandWorked(testDB.runCommand(cmd));
newStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1}));
verifyServerStatusChange(serverStatus.opWriteConcernCounters,
newStatus.opWriteConcernCounters,
[opName + ".noneInfo.CWWC.wtag.myTag", opName + ".none"],
inc);

// Run command with writeConcern {j: true}. This should be counted as having no 'w' value.
resetCollection(setupCommand);
serverStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1}));
verifyServerStatusFields(serverStatus);
assert.commandWorked(
testDB.runCommand(Object.assign(Object.assign({}, cmd), {writeConcern: {j: true}})));
newStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1}));
verifyServerStatusChange(serverStatus.opWriteConcernCounters,
newStatus.opWriteConcernCounters,
[opName + ".noneInfo.implicitDefault.wnum.1", opName + ".none"],
inc);
cmdsWithNoWCProvided.forEach(cmd => {
serverStatus = assert.commandWorked(primary.adminCommand({serverStatus: 1}));
verifyServerStatusFields(serverStatus);
assert.commandWorked(testDB.runCommand(cmd));
newStatus = assert.commandWorked(primary.adminCommand({serverStatus: 1}));
verifyServerStatusChange(serverStatus.opWriteConcernCounters,
newStatus.opWriteConcernCounters,
[opName + ".noneInfo.CWWC.wtag.myTag", opName + ".none"],
inc);
});

// Run command with writeConcern {w: "majority"}.
resetCollection(setupCommand);
serverStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1}));
serverStatus = assert.commandWorked(primary.adminCommand({serverStatus: 1}));
verifyServerStatusFields(serverStatus);
assert.commandWorked(
testDB.runCommand(Object.assign(Object.assign({}, cmd), {writeConcern: {w: "majority"}})));
newStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1}));
newStatus = assert.commandWorked(primary.adminCommand({serverStatus: 1}));
verifyServerStatusChange(serverStatus.opWriteConcernCounters,
newStatus.opWriteConcernCounters,
[opName + ".wmajority"],
inc);

// Run command with writeConcern {w: 0}.
resetCollection(setupCommand);
serverStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1}));
serverStatus = assert.commandWorked(primary.adminCommand({serverStatus: 1}));
verifyServerStatusFields(serverStatus);
assert.commandWorked(
testDB.runCommand(Object.assign(Object.assign({}, cmd), {writeConcern: {w: 0}})));
newStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1}));
verifyServerStatusChange(serverStatus.opWriteConcernCounters,
newStatus.opWriteConcernCounters,
[opName + ".wnum.0"],
inc);
assert.soon(() => {
newStatus = assert.commandWorked(primary.adminCommand({serverStatus: 1}));
try {
verifyServerStatusChange(serverStatus.opWriteConcernCounters,
newStatus.opWriteConcernCounters,
[opName + ".wnum.0"],
inc);
} catch (e) {
return false;
}
return true;
});

// Run command with writeConcern {w: 1}.
resetCollection(setupCommand);
serverStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1}));
serverStatus = assert.commandWorked(primary.adminCommand({serverStatus: 1}));
verifyServerStatusFields(serverStatus);
assert.commandWorked(
testDB.runCommand(Object.assign(Object.assign({}, cmd), {writeConcern: {w: 1}})));
newStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1}));
newStatus = assert.commandWorked(primary.adminCommand({serverStatus: 1}));
verifyServerStatusChange(serverStatus.opWriteConcernCounters,
newStatus.opWriteConcernCounters,
[opName + ".wnum.1"],
inc);

// Run command with writeConcern {w: 2}.
resetCollection(setupCommand);
serverStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1}));
serverStatus = assert.commandWorked(primary.adminCommand({serverStatus: 1}));
verifyServerStatusFields(serverStatus);
assert.commandWorked(
testDB.runCommand(Object.assign(Object.assign({}, cmd), {writeConcern: {w: 2}})));
newStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1}));
newStatus = assert.commandWorked(primary.adminCommand({serverStatus: 1}));
verifyServerStatusChange(serverStatus.opWriteConcernCounters,
newStatus.opWriteConcernCounters,
[opName + ".wnum.2"],
inc);

// Run command with writeConcern {w: "myTag"}.
resetCollection(setupCommand);
serverStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1}));
serverStatus = assert.commandWorked(primary.adminCommand({serverStatus: 1}));
verifyServerStatusFields(serverStatus);
assert.commandWorked(
testDB.runCommand(Object.assign(Object.assign({}, cmd), {writeConcern: {w: "myTag"}})));
newStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1}));
newStatus = assert.commandWorked(primary.adminCommand({serverStatus: 1}));
verifyServerStatusChange(serverStatus.opWriteConcernCounters,
newStatus.opWriteConcernCounters,
[opName + ".wtag.myTag"],
Expand Down Expand Up @@ -300,4 +303,4 @@ for (const isPSASet of [true, false]) {
1,
isPSASet,
{insert: collName, documents: [{_id: 0}]});
}
}

0 comments on commit 8ecb0d8

Please sign in to comment.