mirror of
https://github.com/mongodb/mongo.git
synced 2024-12-01 09:32:32 +01:00
SERVER-55702 Update 'defaultRWConcern' section of serverStatus
This commit is contained in:
parent
065762a395
commit
28206ffd75
@ -12,12 +12,9 @@ load("jstests/libs/write_concern_util.js"); // For isDefaultWriteConcernMajorit
|
||||
|
||||
// Verifies the transaction server status response has the fields that we expect.
|
||||
function verifyServerStatus(conn,
|
||||
{expectedRC, expectedWC, expectNoDefaultsDocument, expectNothing}) {
|
||||
{expectedRC, expectedWC, expectNoDefaultsDocument, expectNothing},
|
||||
isImplicitDefaultWCMajority) {
|
||||
const res = assert.commandWorked(conn.adminCommand({serverStatus: 1}));
|
||||
if (isDefaultWriteConcernMajorityFlagEnabled(conn) && !expectedWC) {
|
||||
expectedWC = {w: "majority", wtimeout: 0};
|
||||
}
|
||||
|
||||
if (expectNothing) {
|
||||
assert.eq(undefined, res.defaultRWConcern, tojson(res.defaultRWConcern));
|
||||
return;
|
||||
@ -26,6 +23,20 @@ function verifyServerStatus(conn,
|
||||
assert.hasFields(res, ["defaultRWConcern"]);
|
||||
const defaultsRes = res.defaultRWConcern;
|
||||
|
||||
if (isDefaultWriteConcernMajorityFlagEnabled(conn)) {
|
||||
assert.hasFields(defaultsRes, ["defaultWriteConcernSource"]);
|
||||
if (!expectedWC) {
|
||||
assert.eq("implicit", defaultsRes.defaultWriteConcernSource, tojson(defaultsRes));
|
||||
if (isImplicitDefaultWCMajority) {
|
||||
expectedWC = {w: "majority", wtimeout: 0};
|
||||
}
|
||||
} else {
|
||||
assert.eq("global", defaultsRes.defaultWriteConcernSource, tojson(defaultsRes));
|
||||
}
|
||||
} else {
|
||||
assert.eq(undefined, defaultsRes.defaultWriteConcernSource);
|
||||
}
|
||||
|
||||
if (expectedRC) {
|
||||
assert.eq(expectedRC, defaultsRes.defaultReadConcern, tojson(defaultsRes));
|
||||
} else {
|
||||
@ -52,24 +63,25 @@ function verifyServerStatus(conn,
|
||||
}
|
||||
}
|
||||
|
||||
function testServerStatus(conn) {
|
||||
function testServerStatus(conn, isImplicitDefaultWCMajority) {
|
||||
// When no defaults have been set.
|
||||
verifyServerStatus(conn, {expectNoDefaultsDocument: true});
|
||||
verifyServerStatus(conn, {expectNoDefaultsDocument: true}, isImplicitDefaultWCMajority);
|
||||
|
||||
// When only read concern is set.
|
||||
assert.commandWorked(
|
||||
conn.adminCommand({setDefaultRWConcern: 1, defaultReadConcern: {level: "majority"}}));
|
||||
verifyServerStatus(conn, {expectedRC: {level: "majority"}});
|
||||
verifyServerStatus(conn, {expectedRC: {level: "majority"}}, isImplicitDefaultWCMajority);
|
||||
|
||||
// When read concern is explicitly unset and write concern is unset.
|
||||
assert.commandWorked(conn.adminCommand(
|
||||
{setDefaultRWConcern: 1, defaultReadConcern: {}, defaultWriteConcern: {}}));
|
||||
verifyServerStatus(conn, {});
|
||||
verifyServerStatus(conn, {}, isImplicitDefaultWCMajority);
|
||||
|
||||
// When only write concern is set.
|
||||
assert.commandWorked(conn.adminCommand(
|
||||
{setDefaultRWConcern: 1, defaultReadConcern: {}, defaultWriteConcern: {w: "majority"}}));
|
||||
verifyServerStatus(conn, {expectedWC: {w: "majority", wtimeout: 0}});
|
||||
verifyServerStatus(
|
||||
conn, {expectedWC: {w: "majority", wtimeout: 0}}, isImplicitDefaultWCMajority);
|
||||
|
||||
// When both read and write concern are set.
|
||||
assert.commandWorked(conn.adminCommand({
|
||||
@ -78,7 +90,8 @@ function testServerStatus(conn) {
|
||||
defaultWriteConcern: {w: "majority"}
|
||||
}));
|
||||
verifyServerStatus(conn,
|
||||
{expectedRC: {level: "majority"}, expectedWC: {w: "majority", wtimeout: 0}});
|
||||
{expectedRC: {level: "majority"}, expectedWC: {w: "majority", wtimeout: 0}},
|
||||
isImplicitDefaultWCMajority);
|
||||
|
||||
// When the defaults document has been deleted.
|
||||
assert.commandWorked(conn.getDB("config").settings.remove({_id: "ReadWriteConcernDefaults"}));
|
||||
@ -88,7 +101,7 @@ function testServerStatus(conn) {
|
||||
const res = conn.adminCommand({getDefaultRWConcern: 1, inMemory: true});
|
||||
return !res.hasOwnProperty("updateOpTime");
|
||||
}, "mongos failed to pick up deleted default rwc", undefined, 1000, {runHangAnalyzer: false});
|
||||
verifyServerStatus(conn, {expectNoDefaultsDocument: true});
|
||||
verifyServerStatus(conn, {expectNoDefaultsDocument: true}, isImplicitDefaultWCMajority);
|
||||
}
|
||||
|
||||
function testFTDC(conn, ftdcDirPath, expectNothingOnRotation = false) {
|
||||
@ -140,16 +153,17 @@ jsTestLog("Testing sharded cluster...");
|
||||
configOptions: {setParameter: {diagnosticDataCollectionDirectoryPath: testPathConfig}}
|
||||
});
|
||||
|
||||
testServerStatus(st.s);
|
||||
testServerStatus(st.s, true /* isImplicitDefaultWCMajority */);
|
||||
testFTDC(st.s, testPathMongos);
|
||||
|
||||
testServerStatus(st.configRS.getPrimary());
|
||||
testServerStatus(st.configRS.getPrimary(), true /* isImplicitDefaultWCMajority */);
|
||||
testFTDC(st.configRS.getPrimary(), testPathConfig);
|
||||
|
||||
// Set a default before verifying it isn't included by shards.
|
||||
assert.commandWorked(
|
||||
st.s.adminCommand({setDefaultRWConcern: 1, defaultWriteConcern: {w: "majority"}}));
|
||||
verifyServerStatus(st.rs0.getPrimary(), {expectNothing: true});
|
||||
verifyServerStatus(
|
||||
st.rs0.getPrimary(), {expectNothing: true}, true /* isImplicitDefaultWCMajority */);
|
||||
testFTDC(st.rs0.getPrimary(), testPathShard, true /* expectNothingOnRotation */);
|
||||
|
||||
st.stop();
|
||||
@ -163,19 +177,29 @@ jsTestLog("Testing plain replica set...");
|
||||
rst.startSet();
|
||||
rst.initiate();
|
||||
|
||||
testServerStatus(rst.getPrimary());
|
||||
testServerStatus(rst.getPrimary(), true /* isImplicitDefaultWCMajority */);
|
||||
testFTDC(rst.getPrimary(), testPath);
|
||||
|
||||
rst.stopSet();
|
||||
}
|
||||
|
||||
jsTestLog("Testing server status for plain replica set with implicit default WC {w:1}");
|
||||
{
|
||||
const rst = new ReplSetTest({nodes: [{}, {}, {arbiter: true}]});
|
||||
rst.startSet();
|
||||
rst.initiate();
|
||||
|
||||
testServerStatus(rst.getPrimary(), false /* isImplicitDefaultWCMajority */);
|
||||
rst.stopSet();
|
||||
}
|
||||
|
||||
jsTestLog("Testing standalone server...");
|
||||
{
|
||||
const testPath = MongoRunner.toRealPath("ftdc_dir_standalone");
|
||||
const standalone =
|
||||
MongoRunner.runMongod({setParameter: {diagnosticDataCollectionDirectoryPath: testPath}});
|
||||
|
||||
verifyServerStatus(standalone, {expectNothing: true});
|
||||
verifyServerStatus(standalone, {expectNothing: true}, true /* isImplicitDefaultWCMajority */);
|
||||
testFTDC(standalone, testPath, true /* expectNothingOnRotation */);
|
||||
|
||||
MongoRunner.stopMongod(standalone);
|
||||
|
@ -9,7 +9,10 @@ load("jstests/libs/write_concern_util.js"); // For isDefaultWriteConcernMajorit
|
||||
// Asserts a set/get default RWC command response or persisted document contains the expected
|
||||
// fields. Assumes a default read or write concern has been set previously and the response was not
|
||||
// generated by a getDefaultRWConcern command with inMemory=true.
|
||||
function verifyFields(res, {expectRC, expectWC, isPersistedDocument}) {
|
||||
function verifyFields(res,
|
||||
{expectRC, expectWC, isPersistedDocument},
|
||||
isDefaultWCMajorityFlagEnabled,
|
||||
isImplicitDefaultWCMajority) {
|
||||
// These fields are always set once a read or write concern has been set at least once.
|
||||
let expectedFields = ["updateOpTime", "updateWallClockTime", "localUpdateWallClockTime"];
|
||||
let unexpectedFields = ["inMemory"];
|
||||
@ -20,12 +23,18 @@ function verifyFields(res, {expectRC, expectWC, isPersistedDocument}) {
|
||||
unexpectedFields.push("defaultReadConcern");
|
||||
}
|
||||
|
||||
if (expectWC) {
|
||||
if (expectWC || (isImplicitDefaultWCMajority && !isPersistedDocument)) {
|
||||
expectedFields.push("defaultWriteConcern");
|
||||
} else {
|
||||
unexpectedFields.push("defaultWriteConcern");
|
||||
}
|
||||
|
||||
if (isDefaultWCMajorityFlagEnabled) {
|
||||
expectedFields.push("defaultWriteConcernSource");
|
||||
} else {
|
||||
unexpectedFields.push("defaultWriteConcernSource");
|
||||
}
|
||||
|
||||
// localUpdateWallClockTime is generated by the in-memory cache and is not stored in the
|
||||
// persisted document.
|
||||
if (isPersistedDocument) {
|
||||
@ -38,6 +47,13 @@ function verifyFields(res, {expectRC, expectWC, isPersistedDocument}) {
|
||||
assert(!res.hasOwnProperty(field),
|
||||
`response unexpectedly had field '${field}', res: ${tojson(res)}`);
|
||||
});
|
||||
if (isDefaultWCMajorityFlagEnabled) {
|
||||
if (expectWC) {
|
||||
assert.eq(res.defaultWriteConcernSource, "global", tojson(res));
|
||||
} else {
|
||||
assert.eq(res.defaultWriteConcernSource, "implicit", tojson(res));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function verifyDefaultRWCommandsInvalidInput(conn) {
|
||||
@ -115,13 +131,20 @@ function verifyDefaultRWCommandsInvalidInput(conn) {
|
||||
}
|
||||
|
||||
// Verifies the default responses for the default RWC commands and the default persisted state.
|
||||
function verifyDefaultState(conn) {
|
||||
function verifyDefaultState(conn, isDefaultWCMajorityFlagEnabled, isImplicitDefaultWCMajority) {
|
||||
const res = assert.commandWorked(conn.adminCommand({getDefaultRWConcern: 1}));
|
||||
const inMemoryRes =
|
||||
assert.commandWorked(conn.adminCommand({getDefaultRWConcern: 1, inMemory: true}));
|
||||
|
||||
// localUpdateWallClockTime is set when a node refreshes its defaults, even if none are found.
|
||||
const expectedFields = ["localUpdateWallClockTime"];
|
||||
if (isImplicitDefaultWCMajority) {
|
||||
expectedFields.push("defaultWriteConcern");
|
||||
}
|
||||
if (isDefaultWCMajorityFlagEnabled) {
|
||||
expectedFields.push("defaultWriteConcernSource");
|
||||
}
|
||||
|
||||
expectedFields.forEach(field => {
|
||||
assert(res.hasOwnProperty(field),
|
||||
`response did not have field '${field}', res: ${tojson(res)}`);
|
||||
@ -130,9 +153,19 @@ function verifyDefaultState(conn) {
|
||||
});
|
||||
assert.eq(inMemoryRes.inMemory, true, tojson(inMemoryRes));
|
||||
|
||||
if (isDefaultWCMajorityFlagEnabled) {
|
||||
assert.eq(res.defaultWriteConcernSource, "implicit", tojson(res));
|
||||
assert.eq(inMemoryRes.defaultWriteConcernSource, "implicit", tojson(inMemoryRes));
|
||||
}
|
||||
|
||||
// No other fields should be returned if neither a default read nor write concern has been set.
|
||||
const unexpectedFields =
|
||||
["defaultReadConcern", "defaultWriteConcern", "updateOpTime", "updateWallClockTime"];
|
||||
const unexpectedFields = ["defaultReadConcern", "updateOpTime", "updateWallClockTime"];
|
||||
if (!isImplicitDefaultWCMajority) {
|
||||
unexpectedFields.push("defaultWriteConcern");
|
||||
}
|
||||
if (!isDefaultWCMajorityFlagEnabled) {
|
||||
unexpectedFields.push("defaultWriteConcernSource");
|
||||
}
|
||||
unexpectedFields.forEach(field => {
|
||||
assert(!res.hasOwnProperty(field),
|
||||
`response unexpectedly had field '${field}', res: ${tojson(res)}`);
|
||||
@ -146,7 +179,8 @@ function verifyDefaultState(conn) {
|
||||
assert.eq(null, getPersistedRWCDocument(conn));
|
||||
}
|
||||
|
||||
function verifyDefaultRWCommandsValidInputOnSuccess(conn) {
|
||||
function verifyDefaultRWCommandsValidInputOnSuccess(
|
||||
conn, isDefaultWCMajorityFlagEnabled, isImplicitDefaultWCMajority) {
|
||||
//
|
||||
// Test getDefaultRWConcern when neither read nor write concern are set.
|
||||
//
|
||||
@ -170,22 +204,34 @@ function verifyDefaultRWCommandsValidInputOnSuccess(conn) {
|
||||
// Test setDefaultRWConcern when only read concern is set.
|
||||
verifyFields(assert.commandWorked(conn.adminCommand(
|
||||
{setDefaultRWConcern: 1, defaultReadConcern: {level: "local"}})),
|
||||
{expectRC: true, expectWC: false});
|
||||
{expectRC: true, expectWC: false},
|
||||
isDefaultWCMajorityFlagEnabled,
|
||||
isImplicitDefaultWCMajority);
|
||||
verifyFields(getPersistedRWCDocument(conn),
|
||||
{expectRC: true, expectWC: false, isPersistedDocument: true});
|
||||
{expectRC: true, expectWC: false, isPersistedDocument: true},
|
||||
isDefaultWCMajorityFlagEnabled,
|
||||
isImplicitDefaultWCMajority);
|
||||
|
||||
// Test getDefaultRWConcern when only read concern is set.
|
||||
verifyFields(assert.commandWorked(conn.adminCommand({getDefaultRWConcern: 1})),
|
||||
{expectRC: true, expectWC: false});
|
||||
{expectRC: true, expectWC: false},
|
||||
isDefaultWCMajorityFlagEnabled,
|
||||
isImplicitDefaultWCMajority);
|
||||
|
||||
// Test unsetting read concern.
|
||||
verifyFields(
|
||||
assert.commandWorked(conn.adminCommand({setDefaultRWConcern: 1, defaultReadConcern: {}})),
|
||||
{expectRC: false, expectWC: false});
|
||||
{expectRC: false, expectWC: false},
|
||||
isDefaultWCMajorityFlagEnabled,
|
||||
isImplicitDefaultWCMajority);
|
||||
verifyFields(getPersistedRWCDocument(conn),
|
||||
{expectRC: false, expectWC: false, isPersistedDocument: true});
|
||||
{expectRC: false, expectWC: false, isPersistedDocument: true},
|
||||
isDefaultWCMajorityFlagEnabled,
|
||||
isImplicitDefaultWCMajority);
|
||||
verifyFields(assert.commandWorked(conn.adminCommand({getDefaultRWConcern: 1})),
|
||||
{expectRC: false, expectWC: false});
|
||||
{expectRC: false, expectWC: false},
|
||||
isDefaultWCMajorityFlagEnabled,
|
||||
isImplicitDefaultWCMajority);
|
||||
|
||||
//
|
||||
// Test getting and setting write concern.
|
||||
@ -194,9 +240,13 @@ function verifyDefaultRWCommandsValidInputOnSuccess(conn) {
|
||||
// Empty write concern is allowed if write concern has not already been set.
|
||||
verifyFields(
|
||||
assert.commandWorked(conn.adminCommand({setDefaultRWConcern: 1, defaultWriteConcern: {}})),
|
||||
{expectRC: false, expectWC: false});
|
||||
{expectRC: false, expectWC: false},
|
||||
isDefaultWCMajorityFlagEnabled,
|
||||
isImplicitDefaultWCMajority);
|
||||
verifyFields(getPersistedRWCDocument(conn),
|
||||
{expectRC: false, expectWC: false, isPersistedDocument: true});
|
||||
{expectRC: false, expectWC: false, isPersistedDocument: true},
|
||||
isDefaultWCMajorityFlagEnabled,
|
||||
isImplicitDefaultWCMajority);
|
||||
|
||||
// Test setRWConcern when only write concern is set.
|
||||
assert.commandWorked(conn.adminCommand({setDefaultRWConcern: 1, defaultWriteConcern: {w: 1}}));
|
||||
@ -207,13 +257,19 @@ function verifyDefaultRWCommandsValidInputOnSuccess(conn) {
|
||||
|
||||
verifyFields(assert.commandWorked(
|
||||
conn.adminCommand({setDefaultRWConcern: 1, defaultWriteConcern: {w: 1}})),
|
||||
{expectRC: false, expectWC: true});
|
||||
{expectRC: false, expectWC: true},
|
||||
isDefaultWCMajorityFlagEnabled,
|
||||
isImplicitDefaultWCMajority);
|
||||
verifyFields(getPersistedRWCDocument(conn),
|
||||
{expectRC: false, expectWC: true, isPersistedDocument: true});
|
||||
{expectRC: false, expectWC: true, isPersistedDocument: true},
|
||||
isDefaultWCMajorityFlagEnabled,
|
||||
isImplicitDefaultWCMajority);
|
||||
|
||||
// Test getRWConcern when only write concern is set.
|
||||
verifyFields(assert.commandWorked(conn.adminCommand({getDefaultRWConcern: 1})),
|
||||
{expectRC: false, expectWC: true});
|
||||
{expectRC: false, expectWC: true},
|
||||
isDefaultWCMajorityFlagEnabled,
|
||||
isImplicitDefaultWCMajority);
|
||||
|
||||
//
|
||||
// Test getting and setting both read and write concern.
|
||||
@ -223,13 +279,19 @@ function verifyDefaultRWCommandsValidInputOnSuccess(conn) {
|
||||
defaultReadConcern: {level: "local"},
|
||||
defaultWriteConcern: {w: 1}
|
||||
})),
|
||||
{expectRC: true, expectWC: true});
|
||||
{expectRC: true, expectWC: true},
|
||||
isDefaultWCMajorityFlagEnabled,
|
||||
isImplicitDefaultWCMajority);
|
||||
verifyFields(getPersistedRWCDocument(conn),
|
||||
{expectRC: true, expectWC: true, isPersistedDocument: true});
|
||||
{expectRC: true, expectWC: true, isPersistedDocument: true},
|
||||
isDefaultWCMajorityFlagEnabled,
|
||||
isImplicitDefaultWCMajority);
|
||||
|
||||
// Test getRWConcern when both read and write concern are set.
|
||||
verifyFields(assert.commandWorked(conn.adminCommand({getDefaultRWConcern: 1})),
|
||||
{expectRC: true, expectWC: true});
|
||||
{expectRC: true, expectWC: true},
|
||||
isDefaultWCMajorityFlagEnabled,
|
||||
isImplicitDefaultWCMajority);
|
||||
}
|
||||
|
||||
function getPersistedRWCDocument(conn) {
|
||||
@ -255,22 +317,20 @@ jsTestLog("Testing standalone mongod...");
|
||||
MongoRunner.stopMongod(standalone);
|
||||
}
|
||||
|
||||
jsTestLog("Testing standalone replica set...");
|
||||
jsTestLog("Testing standalone replica set with implicit default write concern majority...");
|
||||
{
|
||||
const rst = new ReplSetTest({nodes: 2});
|
||||
rst.startSet();
|
||||
rst.initiate();
|
||||
|
||||
// TODO (SERVER-56643): Fix the test to work with the new default write concern.
|
||||
if (isDefaultWriteConcernMajorityFlagEnabled(rst.getPrimary())) {
|
||||
jsTestLog("Skipping test because the default WC majority feature flag is enabled.");
|
||||
rst.stopSet();
|
||||
return;
|
||||
}
|
||||
|
||||
// Primary succeeds.
|
||||
verifyDefaultState(rst.getPrimary());
|
||||
verifyDefaultRWCommandsValidInputOnSuccess(rst.getPrimary());
|
||||
const isDefaultWCMajorityFlagEnabled =
|
||||
isDefaultWriteConcernMajorityFlagEnabled(rst.getPrimary());
|
||||
const isImplicitDefaultWCMajority = isDefaultWCMajorityFlagEnabled;
|
||||
verifyDefaultState(
|
||||
rst.getPrimary(), isDefaultWCMajorityFlagEnabled, isImplicitDefaultWCMajority);
|
||||
verifyDefaultRWCommandsValidInputOnSuccess(
|
||||
rst.getPrimary(), isDefaultWCMajorityFlagEnabled, isImplicitDefaultWCMajority);
|
||||
verifyDefaultRWCommandsInvalidInput(rst.getPrimary());
|
||||
|
||||
// Secondary can run getDefaultRWConcern, but not setDefaultRWConcern.
|
||||
@ -283,18 +343,41 @@ jsTestLog("Testing standalone replica set...");
|
||||
rst.stopSet();
|
||||
}
|
||||
|
||||
jsTestLog("Testing sharded cluster...");
|
||||
jsTestLog("Testing standalone replica set with implicit default write concern {w:1}...");
|
||||
{
|
||||
const rst = new ReplSetTest({nodes: [{}, {}, {arbiter: true}]});
|
||||
rst.startSet();
|
||||
rst.initiate();
|
||||
|
||||
// Primary succeeds.
|
||||
const isDefaultWCMajorityFlagEnabled =
|
||||
isDefaultWriteConcernMajorityFlagEnabled(rst.getPrimary());
|
||||
verifyDefaultState(
|
||||
rst.getPrimary(), isDefaultWCMajorityFlagEnabled, false /* isImplicitDefaultWCMajority */);
|
||||
verifyDefaultRWCommandsValidInputOnSuccess(
|
||||
rst.getPrimary(), isDefaultWCMajorityFlagEnabled, false /* isImplicitDefaultWCMajority */);
|
||||
verifyDefaultRWCommandsInvalidInput(rst.getPrimary());
|
||||
|
||||
// Secondary can run getDefaultRWConcern, but not setDefaultRWConcern.
|
||||
assert.commandWorked(rst.getSecondary().adminCommand({getDefaultRWConcern: 1}));
|
||||
assert.commandFailedWithCode(
|
||||
rst.getSecondary().adminCommand(
|
||||
{setDefaultRWConcern: 1, defaultReadConcern: {level: "local"}}),
|
||||
ErrorCodes.NotWritablePrimary);
|
||||
|
||||
rst.stopSet();
|
||||
}
|
||||
|
||||
jsTestLog("Testing sharded cluster with implicit default write concern majority...");
|
||||
{
|
||||
let st = new ShardingTest({shards: 1, rs: {nodes: 2}});
|
||||
|
||||
if (isDefaultWriteConcernMajorityFlagEnabled(st.s)) {
|
||||
jsTestLog("Skipping test because the default WC majority feature flag is enabled.");
|
||||
st.stop();
|
||||
return;
|
||||
}
|
||||
// Mongos succeeds.
|
||||
verifyDefaultState(st.s);
|
||||
verifyDefaultRWCommandsValidInputOnSuccess(st.s);
|
||||
let isDefaultWCMajorityFlagEnabled = isDefaultWriteConcernMajorityFlagEnabled(st.s);
|
||||
let isImplicitDefaultWCMajority = isDefaultWCMajorityFlagEnabled;
|
||||
verifyDefaultState(st.s, isDefaultWCMajorityFlagEnabled, isImplicitDefaultWCMajority);
|
||||
verifyDefaultRWCommandsValidInputOnSuccess(
|
||||
st.s, isDefaultWCMajorityFlagEnabled, isImplicitDefaultWCMajority);
|
||||
verifyDefaultRWCommandsInvalidInput(st.s);
|
||||
|
||||
// Shard node fails.
|
||||
@ -310,8 +393,57 @@ jsTestLog("Testing sharded cluster...");
|
||||
st.stop();
|
||||
st = new ShardingTest({shards: 1, rs: {nodes: 2}});
|
||||
// Config server primary succeeds.
|
||||
verifyDefaultState(st.configRS.getPrimary());
|
||||
verifyDefaultRWCommandsValidInputOnSuccess(st.configRS.getPrimary());
|
||||
isDefaultWCMajorityFlagEnabled =
|
||||
isDefaultWriteConcernMajorityFlagEnabled(st.configRS.getPrimary());
|
||||
isImplicitDefaultWCMajority = isDefaultWCMajorityFlagEnabled;
|
||||
verifyDefaultState(
|
||||
st.configRS.getPrimary(), isDefaultWCMajorityFlagEnabled, isImplicitDefaultWCMajority);
|
||||
verifyDefaultRWCommandsValidInputOnSuccess(
|
||||
st.configRS.getPrimary(), isDefaultWCMajorityFlagEnabled, isImplicitDefaultWCMajority);
|
||||
verifyDefaultRWCommandsInvalidInput(st.configRS.getPrimary());
|
||||
|
||||
// Config server secondary can run getDefaultRWConcern, but not setDefaultRWConcern.
|
||||
assert.commandWorked(st.configRS.getSecondary().adminCommand({getDefaultRWConcern: 1}));
|
||||
assert.commandFailedWithCode(
|
||||
st.configRS.getSecondary().adminCommand(
|
||||
{setDefaultRWConcern: 1, defaultReadConcern: {level: "local"}}),
|
||||
ErrorCodes.NotWritablePrimary);
|
||||
|
||||
st.stop();
|
||||
}
|
||||
|
||||
jsTestLog("Testing sharded cluster with a PSA replica set...");
|
||||
{
|
||||
let st = new ShardingTest({shards: 1, rs: {nodes: [{}, {}, {arbiter: true}]}});
|
||||
|
||||
// Mongos succeeds.
|
||||
let isDefaultWCMajorityFlagEnabled = isDefaultWriteConcernMajorityFlagEnabled(st.s);
|
||||
let isImplicitDefaultWCMajority = isDefaultWCMajorityFlagEnabled;
|
||||
verifyDefaultState(st.s, isDefaultWCMajorityFlagEnabled, isImplicitDefaultWCMajority);
|
||||
verifyDefaultRWCommandsValidInputOnSuccess(
|
||||
st.s, isDefaultWCMajorityFlagEnabled, isImplicitDefaultWCMajority);
|
||||
verifyDefaultRWCommandsInvalidInput(st.s);
|
||||
|
||||
// Shard node fails.
|
||||
verifyDefaultRWCommandsFailWithCode(st.rs0.getPrimary(), {failureCode: 51301});
|
||||
assert.commandFailedWithCode(st.rs0.getSecondary().adminCommand({getDefaultRWConcern: 1}),
|
||||
51301);
|
||||
// Secondaries fail setDefaultRWConcern before executing the command.
|
||||
assert.commandFailedWithCode(
|
||||
st.rs0.getSecondary().adminCommand(
|
||||
{setDefaultRWConcern: 1, defaultReadConcern: {level: "local"}}),
|
||||
ErrorCodes.NotWritablePrimary);
|
||||
|
||||
st.stop();
|
||||
st = new ShardingTest({shards: 1, rs: {nodes: 2}});
|
||||
// Config server primary succeeds.
|
||||
isDefaultWCMajorityFlagEnabled =
|
||||
isDefaultWriteConcernMajorityFlagEnabled(st.configRS.getPrimary());
|
||||
isImplicitDefaultWCMajority = isDefaultWCMajorityFlagEnabled;
|
||||
verifyDefaultState(
|
||||
st.configRS.getPrimary(), isDefaultWCMajorityFlagEnabled, isImplicitDefaultWCMajority);
|
||||
verifyDefaultRWCommandsValidInputOnSuccess(
|
||||
st.configRS.getPrimary(), isDefaultWCMajorityFlagEnabled, isImplicitDefaultWCMajority);
|
||||
verifyDefaultRWCommandsInvalidInput(st.configRS.getPrimary());
|
||||
|
||||
// Config server secondary can run getDefaultRWConcern, but not setDefaultRWConcern.
|
||||
|
@ -110,6 +110,12 @@ RWConcernDefault ReadWriteConcernDefaults::generateNewCWRWCToBeSavedOnDisk(
|
||||
rc || wc);
|
||||
|
||||
RWConcernDefault rwc;
|
||||
const bool isDefaultWCMajorityFeatureFlagEnabled =
|
||||
repl::feature_flags::gDefaultWCMajority.isEnabled(serverGlobalParams.featureCompatibility);
|
||||
if (isDefaultWCMajorityFeatureFlagEnabled) {
|
||||
rwc.setDefaultWriteConcernSource(DefaultWriteConcernSourceEnum::kImplicit);
|
||||
}
|
||||
|
||||
if (rc && !rc->isEmpty()) {
|
||||
checkSuitabilityAsDefault(*rc);
|
||||
rwc.setDefaultReadConcern(rc);
|
||||
@ -117,6 +123,9 @@ RWConcernDefault ReadWriteConcernDefaults::generateNewCWRWCToBeSavedOnDisk(
|
||||
if (wc && !wc->usedDefault) {
|
||||
checkSuitabilityAsDefault(*wc);
|
||||
rwc.setDefaultWriteConcern(wc);
|
||||
if (isDefaultWCMajorityFeatureFlagEnabled) {
|
||||
rwc.setDefaultWriteConcernSource(DefaultWriteConcernSourceEnum::kGlobal);
|
||||
}
|
||||
}
|
||||
|
||||
auto* const serviceContext = opCtx->getServiceContext();
|
||||
@ -130,6 +139,10 @@ RWConcernDefault ReadWriteConcernDefaults::generateNewCWRWCToBeSavedOnDisk(
|
||||
}
|
||||
if (!wc && current) {
|
||||
rwc.setDefaultWriteConcern(current->getDefaultWriteConcern());
|
||||
if (isDefaultWCMajorityFeatureFlagEnabled && current->getDefaultWriteConcern() &&
|
||||
!current->getDefaultWriteConcern().get().usedDefault) {
|
||||
rwc.setDefaultWriteConcernSource(DefaultWriteConcernSourceEnum::kGlobal);
|
||||
}
|
||||
}
|
||||
// If the setDefaultRWConcern command tries to unset the global default write concern when it
|
||||
// has already been set, throw an error.
|
||||
@ -213,6 +226,12 @@ ReadWriteConcernDefaults::_getDefaultCWRWCFromDisk(OperationContext* opCtx) {
|
||||
ReadWriteConcernDefaults::RWConcernDefaultAndTime ReadWriteConcernDefaults::getDefault(
|
||||
OperationContext* opCtx) {
|
||||
auto cached = _getDefaultCWRWCFromDisk(opCtx).value_or(RWConcernDefaultAndTime());
|
||||
const bool isDefaultWCMajorityFeatureFlagEnabled =
|
||||
serverGlobalParams.featureCompatibility.isVersionInitialized() &&
|
||||
repl::feature_flags::gDefaultWCMajority.isEnabled(serverGlobalParams.featureCompatibility);
|
||||
if (isDefaultWCMajorityFeatureFlagEnabled && !cached.getDefaultWriteConcernSource()) {
|
||||
cached.setDefaultWriteConcernSource(DefaultWriteConcernSourceEnum::kImplicit);
|
||||
}
|
||||
|
||||
// The implicit default write concern will be w:1 if the feature compatibility version is not
|
||||
// yet initialized. Similarly, if the config hasn't yet been loaded on the node, the default
|
||||
@ -220,10 +239,7 @@ ReadWriteConcernDefaults::RWConcernDefaultAndTime ReadWriteConcernDefaults::getD
|
||||
// we have loaded our config, nodes could change their implicit write concern default. This is
|
||||
// safe since we shouldn't be accepting writes that need a write concern before we have loaded
|
||||
// our config.
|
||||
if (!serverGlobalParams.featureCompatibility.isVersionInitialized() ||
|
||||
!repl::feature_flags::gDefaultWCMajority.isEnabled(
|
||||
serverGlobalParams.featureCompatibility) ||
|
||||
!_implicitDefaultWriteConcernMajority) {
|
||||
if (!isDefaultWCMajorityFeatureFlagEnabled || !_implicitDefaultWriteConcernMajority) {
|
||||
return cached;
|
||||
}
|
||||
|
||||
@ -232,6 +248,9 @@ ReadWriteConcernDefaults::RWConcernDefaultAndTime ReadWriteConcernDefaults::getD
|
||||
cached.setDefaultWriteConcern(WriteConcernOptions(WriteConcernOptions::kMajority,
|
||||
WriteConcernOptions::SyncMode::UNSET,
|
||||
WriteConcernOptions::kNoTimeout));
|
||||
if (isDefaultWCMajorityFeatureFlagEnabled) {
|
||||
cached.setDefaultWriteConcernSource(DefaultWriteConcernSourceEnum::kImplicit);
|
||||
}
|
||||
}
|
||||
|
||||
return cached;
|
||||
|
@ -33,6 +33,16 @@ imports:
|
||||
- "mongo/db/repl/read_concern_args.idl"
|
||||
- "mongo/db/write_concern_options.idl"
|
||||
|
||||
enums:
|
||||
DefaultWriteConcernSource:
|
||||
description: "The source of the default write concern"
|
||||
type: string
|
||||
values:
|
||||
# The default write concern was set implicitly by the server
|
||||
kImplicit: "implicit"
|
||||
# The default write concern was set globally through setDefaultRWConcern
|
||||
kGlobal: "global"
|
||||
|
||||
structs:
|
||||
RWConcernDefault:
|
||||
description: "Represents a set of read/write concern defaults, and associated metadata"
|
||||
@ -58,3 +68,7 @@ structs:
|
||||
used for any recency comparisons."
|
||||
type: date
|
||||
optional: true
|
||||
defaultWriteConcernSource:
|
||||
description: "The source of the default write concern."
|
||||
type: DefaultWriteConcernSource
|
||||
optional: true
|
||||
|
Loading…
Reference in New Issue
Block a user