summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Grebennicov <denis.grebennicov@mongodb.com>2021-12-06 15:42:23 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-12-06 16:13:58 +0000
commit909c30b0ff8488299215ccd5ea96d6e3b625433d (patch)
tree85a01648589e132accb1e6f2bf3610046cfa9cf7
parent23fe0c825d6be1a0f4127c1cf19c997590fc0c42 (diff)
downloadmongo-909c30b0ff8488299215ccd5ea96d6e3b625433d.tar.gz
SERVER-60237 Implement FCV upgrade/downgrade for change stream pre-/post-images
-rw-r--r--jstests/change_streams/change_stream_pre_image_lookup_whole_db_whole_cluster.js4
-rw-r--r--jstests/change_streams/change_streams_lookup_preimage_with_chunk_migration.js1
-rw-r--r--jstests/change_streams/lookup_pit_pre_and_post_image.js4
-rw-r--r--jstests/change_streams/lookup_pre_image.js4
-rw-r--r--jstests/change_streams/write_pit_preimage.js9
-rw-r--r--jstests/core/timeseries/timeseries_collmod.js2
-rw-r--r--jstests/core/timeseries/timeseries_create_collection.js14
-rw-r--r--jstests/libs/change_stream_util.js43
-rw-r--r--jstests/libs/check_unique_indexes.js2
-rw-r--r--jstests/multiVersion/change_streams_pre_and_post_images_upgrade_downgrade.js210
-rw-r--r--jstests/noPassthrough/change_stream_preimages_standalone_mode.js2
-rw-r--r--jstests/noPassthrough/change_streams_pre_and_post_images_in_create_and_collmod.js98
-rw-r--r--jstests/noPassthrough/change_streams_pre_image_removal_job.js5
-rw-r--r--jstests/replsets/change_stream_pit_pre_images.js2
-rw-r--r--jstests/sharding/printShardingStatus.js2
-rw-r--r--src/mongo/db/catalog/clustered_collection_util.cpp2
-rw-r--r--src/mongo/db/catalog/coll_mod.cpp6
-rw-r--r--src/mongo/db/catalog/create_collection.cpp17
-rw-r--r--src/mongo/db/commands/create_command.cpp13
-rw-r--r--src/mongo/db/commands/dbcommands.cpp12
-rw-r--r--src/mongo/db/commands/set_feature_compatibility_version_command.cpp46
-rw-r--r--src/mongo/db/repl/replication_coordinator_external_state_impl.cpp8
22 files changed, 334 insertions, 172 deletions
diff --git a/jstests/change_streams/change_stream_pre_image_lookup_whole_db_whole_cluster.js b/jstests/change_streams/change_stream_pre_image_lookup_whole_db_whole_cluster.js
index fc6fb28680d..7017fc707c2 100644
--- a/jstests/change_streams/change_stream_pre_image_lookup_whole_db_whole_cluster.js
+++ b/jstests/change_streams/change_stream_pre_image_lookup_whole_db_whole_cluster.js
@@ -13,14 +13,14 @@
(function() {
"use strict";
-load("jstests/libs/change_stream_util.js"); // For canRecordPreImagesInConfigDatabase.
+load("jstests/libs/change_stream_util.js"); // For isChangeStreamPreAndPostImagesEnabled.
load("jstests/libs/fixture_helpers.js"); // For FixtureHelpers.
const testDB = db.getSiblingDB(jsTestName());
const adminDB = db.getSiblingDB("admin");
const collWithPreImageName = "coll_with_pre_images";
const collWithNoPreImageName = "coll_with_no_pre_images";
-const canRecordPreImagesInConfigDb = canRecordPreImagesInConfigDatabase(testDB);
+const canRecordPreImagesInConfigDb = isChangeStreamPreAndPostImagesEnabled(testDB);
if (!canRecordPreImagesInConfigDb && FixtureHelpers.isMongos(db)) {
jsTestLog("Skipping test as pre image lookup is not supported in sharded cluster with feature" +
diff --git a/jstests/change_streams/change_streams_lookup_preimage_with_chunk_migration.js b/jstests/change_streams/change_streams_lookup_preimage_with_chunk_migration.js
index d7555601788..2d3e91e1218 100644
--- a/jstests/change_streams/change_streams_lookup_preimage_with_chunk_migration.js
+++ b/jstests/change_streams/change_streams_lookup_preimage_with_chunk_migration.js
@@ -4,7 +4,6 @@
*
* @tags: [
* featureFlagChangeStreamPreAndPostImages,
- * featureFlagClusteredIndexes,
* multiversion_incompatible,
* requires_sharding,
* uses_change_streams,
diff --git a/jstests/change_streams/lookup_pit_pre_and_post_image.js b/jstests/change_streams/lookup_pit_pre_and_post_image.js
index 411625ca9b2..2ff1b2cccd4 100644
--- a/jstests/change_streams/lookup_pit_pre_and_post_image.js
+++ b/jstests/change_streams/lookup_pit_pre_and_post_image.js
@@ -9,12 +9,12 @@
"use strict";
load("jstests/libs/collection_drop_recreate.js"); // For assertDropAndRecreateCollection.
-load("jstests/libs/change_stream_util.js"); // For canRecordPreImagesInConfigDatabase.
+load("jstests/libs/change_stream_util.js"); // For isChangeStreamPreAndPostImagesEnabled.
const testDB = db.getSiblingDB(jsTestName());
const collName = "test";
-if (!canRecordPreImagesInConfigDatabase(testDB)) {
+if (!isChangeStreamPreAndPostImagesEnabled(testDB)) {
const coll = assertDropAndRecreateCollection(testDB, collName);
// If feature flag is off, creating changeStream with new fullDocument arguments should throw.
diff --git a/jstests/change_streams/lookup_pre_image.js b/jstests/change_streams/lookup_pre_image.js
index a9ebbb73611..d7662939d04 100644
--- a/jstests/change_streams/lookup_pre_image.js
+++ b/jstests/change_streams/lookup_pre_image.js
@@ -14,11 +14,11 @@
"use strict";
load("jstests/libs/change_stream_util.js"); // For ChangeStreamTest and
- // canRecordPreImagesInConfigDatabase.
+ // isChangeStreamPreAndPostImagesEnabled.
load("jstests/libs/collection_drop_recreate.js"); // For assert[Drop|Create]Collection.
load("jstests/libs/fixture_helpers.js"); // For FixtureHelpers.
-const canRecordPreImagesInConfigDb = canRecordPreImagesInConfigDatabase(db);
+const canRecordPreImagesInConfigDb = isChangeStreamPreAndPostImagesEnabled(db);
if (!canRecordPreImagesInConfigDb && FixtureHelpers.isMongos(db)) {
jsTestLog("Skipping test as pre image lookup is not supported in sharded cluster with feature" +
diff --git a/jstests/change_streams/write_pit_preimage.js b/jstests/change_streams/write_pit_preimage.js
index 654edc958af..0fd797209c4 100644
--- a/jstests/change_streams/write_pit_preimage.js
+++ b/jstests/change_streams/write_pit_preimage.js
@@ -1,13 +1,10 @@
// Tests that pre-images are stored in the pre-images collection on updates and deletes in
// collections with 'changeStreamPreAndPostImages' being enabled.
// @tags: [
-// requires_fcv_51,
+// requires_fcv_52,
// featureFlagChangeStreamPreAndPostImages,
-// # Clustered index support is required for change stream pre-images collection.
-// featureFlagClusteredIndexes,
// assumes_against_mongod_not_mongos,
// change_stream_does_not_expect_txns,
-// multiversion_incompatible,
// ]
(function() {
"use strict";
@@ -51,8 +48,10 @@ function assertValidChangeStreamPreImageDocument(preImage) {
function testFunc(collOptions = {}) {
let coll = assertDropAndRecreateCollection(testDB, collName, collOptions);
- assertDropCollection(configDB, preImagesCollName);
+
+ // Ensure we test the behavior with a clean state.
const preImagesColl = configDB.getCollection(preImagesCollName);
+ assert.commandWorked(preImagesColl.deleteMany({}));
// Perform an insert and an update modification.
assert.commandWorked(coll.insert(originalDoc));
diff --git a/jstests/core/timeseries/timeseries_collmod.js b/jstests/core/timeseries/timeseries_collmod.js
index b1cc445e9b1..86374d30dbc 100644
--- a/jstests/core/timeseries/timeseries_collmod.js
+++ b/jstests/core/timeseries/timeseries_collmod.js
@@ -55,7 +55,7 @@ assert.commandFailedWithCode(db.runCommand({"collMod": collName, "recordPreImage
assert.commandFailedWithCode(
db.runCommand({"collMod": collName, "changeStreamPreAndPostImages": {enabled: true}}), [
ErrorCodes.InvalidOptions,
- // TODO SERVER-52282: remove the error code.
+ // TODO SERVER-58584: remove the error code.
5846901
]);
diff --git a/jstests/core/timeseries/timeseries_create_collection.js b/jstests/core/timeseries/timeseries_create_collection.js
index feb2f443d26..20de3e8974f 100644
--- a/jstests/core/timeseries/timeseries_create_collection.js
+++ b/jstests/core/timeseries/timeseries_create_collection.js
@@ -68,4 +68,18 @@ collections = assert.commandWorked(testDB.runCommand({listCollections: 1})).curs
jsTestLog('Checking listCollections result: ' + tojson(collections));
assert.isnull(collections.find(entry => entry.name === 'system.buckets.' + coll.getName()));
assert(collections.find(entry => entry.name === coll.getName()));
+
+// Should fail to create a timeseries collection with enabled 'changeStreamPreAndPostImages'
+// option.
+coll.drop();
+assert.commandFailedWithCode(testDB.runCommand({
+ create: coll.getName(),
+ timeseries: {timeField: timeFieldName},
+ changeStreamPreAndPostImages: {enabled: true}
+}),
+ [
+ ErrorCodes.InvalidOptions,
+ // TODO SERVER-58584: remove the error code.
+ 5846901
+ ]);
})();
diff --git a/jstests/libs/change_stream_util.js b/jstests/libs/change_stream_util.js
index c79accceac2..e0fd8a0a93e 100644
--- a/jstests/libs/change_stream_util.js
+++ b/jstests/libs/change_stream_util.js
@@ -45,18 +45,6 @@ function isChangeStreamsRewriteEnabled(db) {
}
/**
- * Returns true if pre-images can be recorded in 'system.preimages' collection, false otherwise.
- */
-function canRecordPreImagesInConfigDatabase(db) {
- // Clustered index feature must be enabled to record pre-images in 'system.preimages'
- // collection.
- const getParam = db.adminCommand({getParameter: 1, featureFlagClusteredIndexes: 1});
- return isChangeStreamPreAndPostImagesEnabled(db) &&
- getParam.hasOwnProperty("featureFlagClusteredIndexes") &&
- getParam.featureFlagClusteredIndexes.value;
-}
-
-/**
* Helper function used internally by ChangeStreamTest. If no passthrough is active, it is exactly
* the same as calling db.runCommand. If a passthrough is active and has defined a function
* 'changeStreamPassthroughAwareRunCommand', then this method will be overridden to allow individual
@@ -578,3 +566,34 @@ function assertChangeStreamPreAndPostImagesCollectionOptionIsAbsent(db, collName
const collectionInfos = db.getCollectionInfos({name: collName});
assert(!collectionInfos[0].options.hasOwnProperty("changeStreamPreAndPostImages"));
}
+
+function findPreImagesCollectionDescriptions(db) {
+ return db.getSiblingDB("config").runCommand("listCollections",
+ {filter: {name: "system.preimages"}});
+}
+
+/**
+ * Asserts that pre-images collection is absent in configDB.
+ */
+function assertPreImagesCollectionIsAbsent(db) {
+ const result = findPreImagesCollectionDescriptions(db);
+ assert.eq(result.cursor.firstBatch.length, 0);
+}
+
+/**
+ * Asserts that pre-images collection is created in the configDB and has clustered index on _id.
+ */
+function assertPreImagesCollectionExists(db) {
+ const collectionInfos = findPreImagesCollectionDescriptions(db);
+ assert.eq(collectionInfos.cursor.firstBatch.length, 1, collectionInfos);
+ const preImagesCollectionDescription = collectionInfos.cursor.firstBatch[0];
+ assert.eq(preImagesCollectionDescription.name, "system.preimages");
+
+ // Verifies that the pre-images collection is clustered by _id.
+ assert(preImagesCollectionDescription.hasOwnProperty("options"),
+ preImagesCollectionDescription);
+ assert(preImagesCollectionDescription.options.hasOwnProperty("clusteredIndex"),
+ preImagesCollectionDescription);
+ const clusteredIndexDescription = preImagesCollectionDescription.options.clusteredIndex;
+ assert(clusteredIndexDescription, preImagesCollectionDescription);
+}
diff --git a/jstests/libs/check_unique_indexes.js b/jstests/libs/check_unique_indexes.js
index 9decdbded64..b64532c98f8 100644
--- a/jstests/libs/check_unique_indexes.js
+++ b/jstests/libs/check_unique_indexes.js
@@ -29,7 +29,7 @@ function checkUniqueIndexFormatVersion(adminDB) {
let currentCollection = currentDatabase.getCollection(c.name);
currentCollection.getIndexes().forEach(function(index) {
- if (index.unique) {
+ if (index.unique && !index.clustered) {
let ifv = currentCollection.aggregate({$collStats: {storageStats: {}}})
.next()
.storageStats.indexDetails[index.name]
diff --git a/jstests/multiVersion/change_streams_pre_and_post_images_upgrade_downgrade.js b/jstests/multiVersion/change_streams_pre_and_post_images_upgrade_downgrade.js
index 60aaf51f050..da6d6e1f957 100644
--- a/jstests/multiVersion/change_streams_pre_and_post_images_upgrade_downgrade.js
+++ b/jstests/multiVersion/change_streams_pre_and_post_images_upgrade_downgrade.js
@@ -1,10 +1,9 @@
/**
* Verifies that it is possible to upgrade a replica set with collections with 'recordPreImages'
* option to use 'changeStreamPreAndPostImages' option, and to do a corresponding downgrade.
- * @tags: [requires_fcv_51,
+ * @tags: [
+ * requires_fcv_52,
* featureFlagChangeStreamPreAndPostImages,
- * # Clustered index support is required for change stream pre-images collection.
- * featureFlagClusteredIndexes,
* ]
*/
(function() {
@@ -18,15 +17,27 @@ load(
"jstests/libs/change_stream_util.js"); // For
// assertChangeStreamPreAndPostImagesCollectionOptionIsEnabled,
// assertChangeStreamPreAndPostImagesCollectionOptionIsAbsent.
+ // assertPreImagesCollectionIsAbsent,
+ // assertPreImagesCollectionExists.
+load("jstests/libs/fail_point_util.js"); // For configureFailPoint.
const collName = "test";
+const latestBinVersion = "latest";
-function runTest(downgradeVersion) {
- const downgradeFCV = binVersionToFCV(downgradeVersion);
+// Checks that the pre-image of the next change event in the change stream equals to the
+// 'expectedPreImage'.
+function assertNextPreImage(changeStream, expectedPreImage) {
+ assert.soon(() => changeStream.hasNext());
+ assert.eq(changeStream.next().fullDocumentBeforeChange, expectedPreImage);
+}
+// Tests "changeStreamPreAndPostImages" option for the "create" and "collMod" commands in downgraded
+// and upgraded FCV states. Tests an FCV downgrade succeeds when no collection with
+// changeStreamPreImages: {enabled: true} exists.
+function testCreateAndCollModCommandsInUpgradedDowngradedFCVStates(downgradeFCV) {
const rst = new ReplSetTest({
nodes: 2,
- nodeOptions: {binVersion: downgradeVersion},
+ nodeOptions: {binVersion: downgradeFCV},
});
rst.startSet();
rst.initiate();
@@ -36,7 +47,7 @@ function runTest(downgradeVersion) {
assertCreateCollection(testDB, collName, {"recordPreImages": true});
// Upgrade the replica set.
- rst.upgradeSet({binVersion: "latest"});
+ rst.upgradeSet({binVersion: latestBinVersion});
testDB = rst.getPrimary().getDB(jsTestName());
// Verify that an attempt to set 'changeStreamPreAndPostImages' option fails for the downgraded
@@ -50,7 +61,7 @@ function runTest(downgradeVersion) {
5846901);
// Set the FCV to the latest.
- testDB.adminCommand({setFeatureCompatibilityVersion: latestFCV});
+ assert.commandWorked(testDB.adminCommand({setFeatureCompatibilityVersion: latestFCV}));
// 'changeStreamPreAndPostImages' option must be absent and 'recordPreImages' option must be set
// to true.
@@ -74,19 +85,182 @@ function runTest(downgradeVersion) {
assertChangeStreamPreAndPostImagesCollectionOptionIsAbsent(testDB, collName);
// Downgrade the FCV.
- testDB.adminCommand({setFeatureCompatibilityVersion: downgradeFCV});
+ assert.commandWorked(testDB.adminCommand({setFeatureCompatibilityVersion: downgradeFCV}));
+
+ // Downgrade the replica set.
+ rst.upgradeSet({binVersion: downgradeFCV});
+ rst.stopSet();
+}
+
+// Tests that when change stream pre-images are recorded on a collection using option
+// recordPreImages: true and, after FCV upgrade, recordPreImages: true option is replaced with
+// changeStreamPreAndPostImages: {enabled: true} , then pre-images are available for all change
+// events in a change stream without interruption. Subsequently, tests a FCV downgrade and switching
+// back from option changeStreamPreAndPostImages: {enabled: true} to recordPreImages: true.
+function testUpgradeDowngradeFromRecordPreImageOptionToChangeStreamPreAndPostImages(downgradeFCV) {
+ // Upgrade scenario.
+ // Upgrade server binary.
+ const rst = new ReplSetTest({
+ nodes: 2,
+ nodeOptions: {binVersion: downgradeFCV},
+ });
+ rst.startSet();
+ rst.initiate();
+ rst.upgradeSet({binVersion: latestBinVersion});
+
+ // Create the collection with recorded pre-images enabled and insert one document.
+ const testDB = rst.getPrimary().getDB(jsTestName());
+ const coll = assertCreateCollection(testDB, collName, {recordPreImages: true});
+ assert.commandWorked(coll.insert({_id: 1, eventId: 1}));
+
+ // Open a change stream with fullDocumentBeforeChange: "required".
+ const changeStream = coll.watch([], {fullDocumentBeforeChange: "required"});
+
+ // Perform an "update" command. Pre-image will be recorded in the oplog.
+ assert.commandWorked(coll.update({_id: 1}, {$inc: {eventId: 1}}));
+
+ // Upgrade to the latest FCV.
+ assert.commandWorked(testDB.adminCommand({setFeatureCompatibilityVersion: latestFCV}));
+
+ // Verify that the pre-images collection is created.
+ assertPreImagesCollectionExists(testDB);
+
+ // Enable change stream pre-images recording for the collection.
+ assert.commandWorked(
+ testDB.runCommand({collMod: collName, changeStreamPreAndPostImages: {enabled: true}}));
+
+ // Issue an "update" command for which the pre-image won't be available after the FCV downgrade.
+ assert.commandWorked(coll.update({_id: 1}, {$inc: {eventId: 1}}));
+
+ // Verify that change stream receives change event with pre-image being set.
+ assertNextPreImage(changeStream, {_id: 1, eventId: 1});
+
+ // Issue an "update" command for which the pre-image won't be available after the FCV downgrade.
+ assert.commandWorked(coll.update({_id: 1}, {$inc: {eventId: 1}}));
+
+ // Downgrade scenario.
+ // Revert to the previous pre-image recording capability available in 5.0.
+ assert.commandWorked(testDB.runCommand({collMod: collName, recordPreImages: true}));
+
+ // Verify that the change stream returns a change event with a pre-image set.
+ assertNextPreImage(changeStream, {_id: 1, eventId: 2});
+
+ // Downgrade the FCV version. Pre-images collection is dropped during the downgrade.
+ assert.commandWorked(testDB.adminCommand({setFeatureCompatibilityVersion: downgradeFCV}));
+
+ // Verify that pre-images collection is dropped.
+ assertPreImagesCollectionIsAbsent(testDB);
+
+ // Verify that reading the next change event fails for change stream with
+ // fullDocumentBeforeChange: "required", as pre-image for this event was recorded in the
+ // pre-images collection.
+ assert.throwsWithCode(() => changeStream.hasNext(), ErrorCodes.NoMatchingDocument);
+
+ rst.stopSet();
+}
+
+// Tests that when change stream pre-images are recorded on a collection using option
+// changeStreamPreAndPostImages: {enabled: true} and, after changeStreamPreAndPostImages option is
+// disabled, then pre-images are unavailable to change stream change events after FCV downgrade.
+function testDowngrade(downgradeFCV) {
+ const rst = new ReplSetTest({
+ nodes: 2,
+ nodeOptions: {binVersion: latestBinVersion},
+ });
+ rst.startSet();
+ rst.initiate();
+
+ // Create the collection with changeStreamPreAndPostImages: {enabled: true} and perform insert
+ // and update operations.
+ const testDB = rst.getPrimary().getDB(jsTestName());
+ const coll =
+ assertCreateCollection(testDB, collName, {changeStreamPreAndPostImages: {enabled: true}});
+ const changeStream = coll.watch([], {fullDocumentBeforeChange: "required"});
+ assert.commandWorked(coll.insert({_id: 1, eventId: 1}));
+ assert.commandWorked(coll.update({_id: 1}, {$inc: {eventId: 1}}));
+
+ // Downgrade scenario.
+ // Issue "collMod" command in order to disable changeStreamPreAndPostImages option.
+ assert.commandWorked(
+ testDB.runCommand({"collMod": collName, changeStreamPreAndPostImages: {enabled: false}}));
+
+ // Downgrade the FCV version.
+ assert.commandWorked(testDB.adminCommand({setFeatureCompatibilityVersion: downgradeFCV}));
+
+ // Verify that the pre-images collection is dropped.
+ assertPreImagesCollectionIsAbsent(testDB);
+
+ // Verify that reading the next change event fails for change stream with
+ // fullDocumentBeforeChange: "required", as pre-image for this event was recorded in the
+ // pre-images collection that no longer exists.
+ assert.throwsWithCode(() => changeStream.hasNext(), ErrorCodes.NoMatchingDocument);
+
+ rst.stopSet();
+}
+
+// Tests that downgrading of the FCV fails if there exists a collection with
+// changeStreamPreAndPostImages: {enabled: true}.
+function testFCVDowngradeFailureWhenChangeStreamPreAndPostImagesEnabledForCollection(downgradeFCV) {
+ const rst = new ReplSetTest({
+ nodes: 2,
+ nodeOptions: {binVersion: latestBinVersion},
+ });
+ rst.startSet();
+ rst.initiate();
+ const testDB = rst.getPrimary().getDB(jsTestName());
+
+ // Pre-images collection must exist upon start-up with the latest FCV.
+ assertPreImagesCollectionExists(testDB);
+ assert.commandWorked(
+ testDB.createCollection("testCollection", {changeStreamPreAndPostImages: {enabled: true}}));
+
+ // Verify that a downgrade of the FCV fails when there is at least one collection with
+ // {changeStreamPreAndPostImages: {enabled: true}} option set.
+ assert.commandFailedWithCode(
+ testDB.adminCommand({setFeatureCompatibilityVersion: downgradeFCV}),
+ ErrorCodes.CannotDowngrade);
+
+ // Verify that the pre-images collection is not dropped in case of a failed FCV downgrade.
+ assertPreImagesCollectionExists(testDB);
+
+ rst.stopSet();
+}
+
+// Tests that FCV upgrade fails if there is an error creating pre-images collection.
+function testFCVUpgradeFailureWhenCreationOfPreImagesCollectionFails(downgradeFCV) {
+ const rst = new ReplSetTest({
+ nodes: 2,
+ nodeOptions: {binVersion: binVersionFromFCV(downgradeFCV)},
+ });
+ rst.startSet();
+ rst.initiate();
+ rst.upgradeSet({binVersion: latestBinVersion});
+ const testDB = rst.getPrimary().getDB(jsTestName());
+ configureFailPoint(rst.getPrimary(), "failPreimagesCollectionCreation", {}, {times: 1});
+
+ // Verify that FCV upgrade fails when creation of the pre-images collection fails.
+ assert.commandFailedWithCode(testDB.adminCommand({setFeatureCompatibilityVersion: latestFCV}),
+ 5868501);
+
+ // Verfiy that FCV version remains unchanged.
+ const fcvDoc = testDB.adminCommand({getParameter: 1, featureCompatibilityVersion: 1});
+ assert.eq(fcvDoc.featureCompatibilityVersion.version, downgradeFCV, fcvDoc);
- // Downgrading the cluster should fail, since the pre-images collection is clustered which is
- // not supported by the downgraded binary.
- try {
- rst.upgradeSet({binVersion: downgradeVersion});
- assert(false);
- } catch (exception) {
- assert.eq(exception.returnCode, MongoRunner.EXIT_UNCAUGHT);
- }
+ // Verify that the pre-images collection is not created.
+ assertPreImagesCollectionIsAbsent(testDB);
rst.stopSet();
}
-runFeatureFlagMultiversionTest('featureFlagChangeStreamPreAndPostImages', runTest);
+runFeatureFlagMultiversionTest('featureFlagChangeStreamPreAndPostImages',
+ testCreateAndCollModCommandsInUpgradedDowngradedFCVStates);
+runFeatureFlagMultiversionTest(
+ 'featureFlagChangeStreamPreAndPostImages',
+ testUpgradeDowngradeFromRecordPreImageOptionToChangeStreamPreAndPostImages);
+runFeatureFlagMultiversionTest('featureFlagChangeStreamPreAndPostImages', testDowngrade);
+runFeatureFlagMultiversionTest(
+ 'featureFlagChangeStreamPreAndPostImages',
+ testFCVDowngradeFailureWhenChangeStreamPreAndPostImagesEnabledForCollection);
+runFeatureFlagMultiversionTest('featureFlagChangeStreamPreAndPostImages',
+ testFCVUpgradeFailureWhenCreationOfPreImagesCollectionFails);
})();
diff --git a/jstests/noPassthrough/change_stream_preimages_standalone_mode.js b/jstests/noPassthrough/change_stream_preimages_standalone_mode.js
index fb9664f17dd..84c8a9a2f0a 100644
--- a/jstests/noPassthrough/change_stream_preimages_standalone_mode.js
+++ b/jstests/noPassthrough/change_stream_preimages_standalone_mode.js
@@ -10,8 +10,6 @@
* requires_replication,
* requires_fcv_52,
* featureFlagChangeStreamPreAndPostImages,
- * # Clustered index support is required for change stream pre-images collection.
- * featureFlagClusteredIndexes,
* # TODO SERVER-58694: remove this tag.
* change_stream_does_not_expect_txns,
* ]
diff --git a/jstests/noPassthrough/change_streams_pre_and_post_images_in_create_and_collmod.js b/jstests/noPassthrough/change_streams_pre_and_post_images_in_create_and_collmod.js
index 2416d7a6a74..6b82ce1d7b7 100644
--- a/jstests/noPassthrough/change_streams_pre_and_post_images_in_create_and_collmod.js
+++ b/jstests/noPassthrough/change_streams_pre_and_post_images_in_create_and_collmod.js
@@ -1,22 +1,17 @@
/*
* Tests that the 'changeStreamPreAndPostImages' option is settable via the collMod and create
* commands. Also tests that this option cannot be set on collections in the 'local', 'admin',
- * 'config' databases as well as timeseries and view collections. Verifies that the pre-images
- * collection is clustered.
+ * 'config' databases as well as on view collections.
* @tags: [
- * requires_fcv_51,
+ * requires_fcv_52,
* featureFlagChangeStreamPreAndPostImages,
- * # Clustered index support is required for change stream pre-images collection.
- * featureFlagClusteredIndexes,
* ]
*/
(function() {
'use strict';
-load("jstests/libs/collection_options.js"); // For assertCollectionOptionIsEnabled,
- // assertCollectionOptionIsAbsent.
-load("jstests/libs/collection_drop_recreate.js"); // For assertDropCollection.
-load("jstests/libs/fail_point_util.js"); // For configureFailPoint, off.
+load("jstests/libs/collection_options.js"); // For assertCollectionOptionIsEnabled,
+ // assertCollectionOptionIsAbsent.
load(
"jstests/libs/change_stream_util.js"); // For
// assertChangeStreamPreAndPostImagesCollectionOptionIsEnabled,
@@ -31,13 +26,7 @@ const collName = 'changeStreamPreAndPostImages';
const collName2 = 'changeStreamPreAndPostImages2';
const collName3 = 'changeStreamPreAndPostImages3';
const collName4 = 'changeStreamPreAndPostImages4';
-const collName5 = 'changeStreamPreAndPostImages5';
-const collName6 = 'changeStreamPreAndPostImages6';
const viewName = "view";
-const preImagesCollName = "system.preimages";
-const createTimeseriesOptions = {
- timeField: "a"
-};
const primary = rsTest.getPrimary();
const adminDB = primary.getDB("admin");
@@ -45,34 +34,6 @@ const localDB = primary.getDB("local");
const configDB = primary.getDB("config");
const testDB = primary.getDB(dbName);
-function findPreImagesCollectionDescriptions() {
- return configDB.runCommand("listCollections", {filter: {name: preImagesCollName}});
-}
-
-function assertPreImagesCollectionIsAbsent() {
- const result = findPreImagesCollectionDescriptions();
- assert.eq(result.cursor.firstBatch.length, 0);
-}
-
-function assertPreImagesCollectionExists() {
- const result = findPreImagesCollectionDescriptions();
- assert.eq(result.cursor.firstBatch[0].name, preImagesCollName);
-}
-
-// Verifies that the pre-images collection is clustered by _id.
-function assertPreImagesCollectionIsClustered() {
- const collectionInfos = findPreImagesCollectionDescriptions();
- assert.eq(collectionInfos.cursor.firstBatch.length, 1, collectionInfos);
- const preImagesCollectionDescription = collectionInfos.cursor.firstBatch[0];
- assert(preImagesCollectionDescription.hasOwnProperty("options"),
- preImagesCollectionDescription);
- assert(preImagesCollectionDescription.options.hasOwnProperty("clusteredIndex"),
- preImagesCollectionDescription);
- const clusteredIndexDescription = preImagesCollectionDescription.options.clusteredIndex;
- assert.eq(clusteredIndexDescription.unique, true, preImagesCollectionDescription);
- assert.eq(clusteredIndexDescription.key, {_id: 1}, preImagesCollectionDescription);
-}
-
// Check that we cannot set 'changeStreamPreAndPostImages' on the local, admin and config databases.
for (const db of [localDB, adminDB, configDB]) {
assert.commandFailedWithCode(
@@ -85,42 +46,26 @@ for (const db of [localDB, adminDB, configDB]) {
ErrorCodes.InvalidOptions);
}
-// Drop the pre-images collection.
-assertDropCollection(configDB, preImagesCollName);
-assertPreImagesCollectionIsAbsent();
-
// Should be able to enable the 'changeStreamPreAndPostImages' via create or collMod.
assert.commandWorked(
testDB.runCommand({create: collName, changeStreamPreAndPostImages: {enabled: true}}));
assertChangeStreamPreAndPostImagesCollectionOptionIsEnabled(testDB, collName);
-assertPreImagesCollectionExists();
-assertPreImagesCollectionIsClustered();
-
-// Drop the pre-images collection.
-assertDropCollection(configDB, preImagesCollName);
-assertPreImagesCollectionIsAbsent();
assert.commandWorked(testDB.runCommand({create: collName2}));
assert.commandWorked(
testDB.runCommand({collMod: collName2, changeStreamPreAndPostImages: {enabled: true}}));
assertChangeStreamPreAndPostImagesCollectionOptionIsEnabled(testDB, collName2);
-assertPreImagesCollectionExists();
// Verify that setting collection options with 'collMod' command does not affect
// 'changeStreamPreAndPostImages' option.
assert.commandWorked(testDB.runCommand({"collMod": collName2, validationLevel: "off"}));
assertChangeStreamPreAndPostImagesCollectionOptionIsEnabled(testDB, collName2);
-assertPreImagesCollectionExists();
// Should successfully disable 'changeStreamPreAndPostImages' using the 'collMod' command.
assert.commandWorked(
testDB.runCommand({collMod: collName2, changeStreamPreAndPostImages: {enabled: false}}));
assertChangeStreamPreAndPostImagesCollectionOptionIsAbsent(testDB, collName2);
-// Should not remove the pre-images collection on disabling 'changeStreamPreAndPostImages'
-// option.
-assertPreImagesCollectionExists();
-
// Both 'recordPreImages' and 'changeStreamPreAndPostImages' may not be enabled at the same
// time.
assert.commandFailedWithCode(
@@ -164,19 +109,11 @@ assert.commandWorked(
assertCollectionOptionIsAbsent(testDB, collName3, "recordPreImages");
assertChangeStreamPreAndPostImagesCollectionOptionIsEnabled(testDB, collName3);
-// Should fail to create a timeseries collection with enabled 'changeStreamPreAndPostImages'
-// option.
-assert.commandFailedWithCode(testDB.runCommand({
- create: collName4,
- timeseries: createTimeseriesOptions,
- changeStreamPreAndPostImages: {enabled: true}
-}),
- ErrorCodes.InvalidOptions);
-
-assert.commandWorked(testDB.runCommand({create: collName4, timeseries: createTimeseriesOptions}));
-assert.commandFailedWithCode(
- testDB.runCommand({collMod: collName4, changeStreamPreAndPostImages: {enabled: true}}),
- ErrorCodes.InvalidOptions);
+// Should set 'recordPreImages' to true and disable 'changeStreamPreAndPostImages' option.
+assert.commandWorked(testDB.runCommand(
+ {create: collName4, recordPreImages: true, changeStreamPreAndPostImages: {enabled: false}}));
+assert.commandWorked(testDB.runCommand(
+ {collMod: collName4, recordPreImages: true, changeStreamPreAndPostImages: {enabled: false}}));
assertChangeStreamPreAndPostImagesCollectionOptionIsAbsent(testDB, collName4);
// Should fail to create a view with enabled 'changeStreamPreAndPostImages' option.
@@ -189,22 +126,5 @@ assert.commandFailedWithCode(
testDB.runCommand({collMod: viewName, changeStreamPreAndPostImages: {enabled: true}}),
ErrorCodes.InvalidOptions);
-// Should fail to run 'create' and 'collMod' commands if creating pre-images collection fails.
-const failpoint = configureFailPoint(primary, "failPreimagesCollectionCreation");
-assert.commandFailedWithCode(
- testDB.runCommand({create: collName5, changeStreamPreAndPostImages: {enabled: true}}), 5868501);
-assert.commandWorked(testDB.runCommand({create: collName5}));
-assert.commandFailedWithCode(
- testDB.runCommand({collMod: collName5, changeStreamPreAndPostImages: {enabled: true}}),
- 5868501);
-failpoint.off();
-
-// Should set 'recordPreImages' to true and disable 'changeStreamPreAndPostImages' option.
-assert.commandWorked(testDB.runCommand(
- {create: collName6, recordPreImages: true, changeStreamPreAndPostImages: {enabled: false}}));
-assert.commandWorked(testDB.runCommand(
- {collMod: collName6, recordPreImages: true, changeStreamPreAndPostImages: {enabled: false}}));
-assertChangeStreamPreAndPostImagesCollectionOptionIsAbsent(testDB, collName6);
-
rsTest.stopSet();
}());
diff --git a/jstests/noPassthrough/change_streams_pre_image_removal_job.js b/jstests/noPassthrough/change_streams_pre_image_removal_job.js
index a256f7bdc50..cb9ba2e8c17 100644
--- a/jstests/noPassthrough/change_streams_pre_image_removal_job.js
+++ b/jstests/noPassthrough/change_streams_pre_image_removal_job.js
@@ -2,13 +2,10 @@
// removed from the pre-images collection via the 'PeriodicChangeStreamExpiredPreImagesRemover'
// periodic job.
// @tags: [
-// requires_fcv_51,
+// requires_fcv_52,
// featureFlagChangeStreamPreAndPostImages,
-// # Clustered index support is required for change stream pre-images collection.
-// featureFlagClusteredIndexes,
// assumes_against_mongod_not_mongos,
// change_stream_does_not_expect_txns,
-// multiversion_incompatible,
// ]
(function() {
"use strict";
diff --git a/jstests/replsets/change_stream_pit_pre_images.js b/jstests/replsets/change_stream_pit_pre_images.js
index 6ef8f6fedbe..726507d0fcf 100644
--- a/jstests/replsets/change_stream_pit_pre_images.js
+++ b/jstests/replsets/change_stream_pit_pre_images.js
@@ -9,8 +9,6 @@
* requires_wiredtiger,
* requires_fcv_52,
* featureFlagChangeStreamPreAndPostImages,
- * # Clustered index support is required for change stream pre-images collection.
- * featureFlagClusteredIndexes,
* ]
*/
(function() {
diff --git a/jstests/sharding/printShardingStatus.js b/jstests/sharding/printShardingStatus.js
index da4081c2ca2..5bd305da1d2 100644
--- a/jstests/sharding/printShardingStatus.js
+++ b/jstests/sharding/printShardingStatus.js
@@ -99,7 +99,7 @@ var config = mongos.getDB("config");
var configCopy = standalone.getDB("configCopy");
config.getCollectionInfos().forEach(function(c) {
// It's illegal to copy the system collections.
- if (c.name == "system.indexBuilds") {
+ if (["system.indexBuilds", "system.preimages"].includes(c.name)) {
return;
}
diff --git a/src/mongo/db/catalog/clustered_collection_util.cpp b/src/mongo/db/catalog/clustered_collection_util.cpp
index 7a7fb99a2b0..382357ea7b0 100644
--- a/src/mongo/db/catalog/clustered_collection_util.cpp
+++ b/src/mongo/db/catalog/clustered_collection_util.cpp
@@ -87,7 +87,7 @@ boost::optional<ClusteredCollectionInfo> parseClusteredInfo(const BSONElement& e
}
bool requiresLegacyFormat(const NamespaceString& nss) {
- return nss.isTimeseriesBucketsCollection();
+ return nss.isTimeseriesBucketsCollection() || nss.isChangeStreamPreImagesCollection();
}
BSONObj formatClusterKeyForListIndexes(const ClusteredCollectionInfo& collInfo) {
diff --git a/src/mongo/db/catalog/coll_mod.cpp b/src/mongo/db/catalog/coll_mod.cpp
index 95c811f2bf0..7205ec2b764 100644
--- a/src/mongo/db/catalog/coll_mod.cpp
+++ b/src/mongo/db/catalog/coll_mod.cpp
@@ -664,12 +664,6 @@ Status _collModInternal(OperationContext* opCtx,
LOGV2(5324200, "CMD: collMod", "cmdObj"_attr = cmd.toBSON(BSONObj()));
}
- if (cmrNew.changeStreamPreAndPostImagesOptions.has_value() &&
- cmrNew.changeStreamPreAndPostImagesOptions->getEnabled()) {
- // Create pre-images collection if it doesn't already exist.
- createChangeStreamPreImagesCollection(opCtx);
- }
-
// With exclusive access to the collection, we can take ownership of the modified docs observed
// by the side write tracker if a unique index conversion is requested.
// This step releases the resources associated with the token and therefore should not be
diff --git a/src/mongo/db/catalog/create_collection.cpp b/src/mongo/db/catalog/create_collection.cpp
index 050859699e8..a7bb318d94b 100644
--- a/src/mongo/db/catalog/create_collection.cpp
+++ b/src/mongo/db/catalog/create_collection.cpp
@@ -477,7 +477,7 @@ Status _createCollection(OperationContext* opCtx,
<< nss);
}
- if ((nss.isTimeseriesBucketsCollection()) != (clusteredIndex->getLegacyFormat())) {
+ if (clustered_util::requiresLegacyFormat(nss) != clusteredIndex->getLegacyFormat()) {
return Status(ErrorCodes::Error(5979703),
"The 'clusteredIndex' legacy format {clusteredIndex: <bool>} is only "
"supported for specific internal collections and vice versa");
@@ -576,16 +576,6 @@ Status createCollection(OperationContext* opCtx,
str::stream() << "Cannot create system collection " << ns
<< " within a transaction.",
!opCtx->inMultiDocumentTransaction() || !ns.isSystem());
- if (options.changeStreamPreAndPostImagesOptions.getEnabled()) {
- tassert(5868500,
- "ChangeStreamPreAndPostImages feature flag must be enabled",
- feature_flags::gFeatureFlagChangeStreamPreAndPostImages.isEnabled(
- serverGlobalParams.featureCompatibility));
-
- // Create preimages collection if it doesn't already exist.
- createChangeStreamPreImagesCollection(opCtx);
- }
-
return _createCollection(opCtx, ns, std::move(options), idIndex);
}
}
@@ -659,16 +649,13 @@ void createChangeStreamPreImagesCollection(OperationContext* opCtx) {
uassert(5868501,
"Failpoint failPreimagesCollectionCreation enabled. Throwing exception",
!MONGO_unlikely(failPreimagesCollectionCreation.shouldFail()));
- tassert(5882500,
- "Failed to create the pre-images collection: clustered indexes feature is not enabled",
- feature_flags::gClusteredIndexes.isEnabled(serverGlobalParams.featureCompatibility));
const auto nss = NamespaceString::kChangeStreamPreImagesNamespace;
CollectionOptions preImagesCollectionOptions;
// Make the collection clustered by _id.
preImagesCollectionOptions.clusteredIndex.emplace(
- clustered_util::makeDefaultClusteredIdIndex());
+ clustered_util::makeCanonicalClusteredInfoForLegacyFormat());
const auto status =
_createCollection(opCtx, nss, std::move(preImagesCollectionOptions), BSONObj());
uassert(status.code(),
diff --git a/src/mongo/db/commands/create_command.cpp b/src/mongo/db/commands/create_command.cpp
index c51145ddf2a..b7751f0f270 100644
--- a/src/mongo/db/commands/create_command.cpp
+++ b/src/mongo/db/commands/create_command.cpp
@@ -285,12 +285,19 @@ public:
cmd.setIdIndex(idIndexSpec);
}
+ const auto isChangeStreamPreAndPostImagesEnabled =
+ (cmd.getChangeStreamPreAndPostImages() &&
+ cmd.getChangeStreamPreAndPostImages()->getEnabled());
+
+ // Acquire shared lock on FCV if 'changeStreamPreAndPostImages' is enabled.
+ boost::optional<FixedFCVRegion> fcvRegion;
+ if (isChangeStreamPreAndPostImagesEnabled) {
+ fcvRegion.emplace(opCtx);
+ }
+
if (feature_flags::gFeatureFlagChangeStreamPreAndPostImages.isEnabled(
serverGlobalParams.featureCompatibility)) {
const auto isRecordPreImagesEnabled = cmd.getRecordPreImages().get_value_or(false);
- const auto isChangeStreamPreAndPostImagesEnabled =
- (cmd.getChangeStreamPreAndPostImages() &&
- cmd.getChangeStreamPreAndPostImages()->getEnabled());
uassert(ErrorCodes::InvalidOptions,
"'recordPreImages' and 'changeStreamPreAndPostImages.enabled' can not be "
"set to true simultaneously",
diff --git a/src/mongo/db/commands/dbcommands.cpp b/src/mongo/db/commands/dbcommands.cpp
index ec54c6c5ce0..78b5f25c93c 100644
--- a/src/mongo/db/commands/dbcommands.cpp
+++ b/src/mongo/db/commands/dbcommands.cpp
@@ -534,13 +534,19 @@ public:
const RequestParser& requestParser,
BSONObjBuilder& result) final {
const auto* cmd = &requestParser.request();
+ const auto isChangeStreamPreAndPostImagesEnabled =
+ (cmd->getChangeStreamPreAndPostImages() &&
+ cmd->getChangeStreamPreAndPostImages()->getEnabled());
+
+ // Acquire shared lock on FCV if 'changeStreamPreAndPostImages' is enabled.
+ boost::optional<FixedFCVRegion> fcvRegion;
+ if (isChangeStreamPreAndPostImagesEnabled) {
+ fcvRegion.emplace(opCtx);
+ }
if (feature_flags::gFeatureFlagChangeStreamPreAndPostImages.isEnabled(
serverGlobalParams.featureCompatibility)) {
const auto isRecordPreImagesEnabled = cmd->getRecordPreImages().get_value_or(false);
- const auto isChangeStreamPreAndPostImagesEnabled =
- (cmd->getChangeStreamPreAndPostImages() &&
- cmd->getChangeStreamPreAndPostImages()->getEnabled());
uassert(ErrorCodes::InvalidOptions,
"'recordPreImages' and 'changeStreamPreAndPostImages.enabled' can not be set "
"to true simultaneously",
diff --git a/src/mongo/db/commands/set_feature_compatibility_version_command.cpp b/src/mongo/db/commands/set_feature_compatibility_version_command.cpp
index 3965c5eaa51..311036f4a32 100644
--- a/src/mongo/db/commands/set_feature_compatibility_version_command.cpp
+++ b/src/mongo/db/commands/set_feature_compatibility_version_command.cpp
@@ -36,6 +36,7 @@
#include "mongo/db/auth/authorization_session.h"
#include "mongo/db/catalog/coll_mod.h"
#include "mongo/db/catalog/collection_catalog_helper.h"
+#include "mongo/db/catalog/create_collection.h"
#include "mongo/db/catalog/database.h"
#include "mongo/db/catalog/database_holder.h"
#include "mongo/db/catalog/drop_collection.h"
@@ -398,6 +399,7 @@ private:
mongo::multiversion::FeatureCompatibilityVersion originalVersion,
const SetFeatureCompatibilityVersion& request,
boost::optional<Timestamp> changeTimestamp) {
+ const auto requestedVersion = request.getCommandParameter();
if (serverGlobalParams.clusterRole == ClusterRole::ConfigServer) {
// Tell the shards to enter phase-1 of setFCV
@@ -480,7 +482,6 @@ private:
opCtx, CommandHelpers::appendMajorityWriteConcern(requestPhase2.toBSON({}))));
// TODO: Remove once FCV 6.0 becomes last-lts
- const auto requestedVersion = request.getCommandParameter();
if (!feature_flags::gFeatureFlagLongCollectionNames.isEnabledOnVersion(
originalVersion) &&
feature_flags::gFeatureFlagLongCollectionNames.isEnabledOnVersion(
@@ -494,6 +495,13 @@ private:
abortAllReshardCollection(opCtx);
}
+ // Create the pre-images collection if the feature flag is enabled on the requested version.
+ // TODO SERVER-61770: Remove once FCV 6.0 becomes last-lts.
+ if (feature_flags::gFeatureFlagChangeStreamPreAndPostImages.isEnabledOnVersion(
+ requestedVersion)) {
+ createChangeStreamPreImagesCollection(opCtx);
+ }
+
hangWhileUpgrading.pauseWhileSet(opCtx);
}
@@ -502,6 +510,9 @@ private:
const SetFeatureCompatibilityVersion& request,
boost::optional<Timestamp> changeTimestamp) {
const auto requestedVersion = request.getCommandParameter();
+ const bool preImagesFeatureFlagDisabledOnDowngradeVersion =
+ !feature_flags::gFeatureFlagChangeStreamPreAndPostImages.isEnabledOnVersion(
+ requestedVersion);
if (serverGlobalParams.clusterRole == ClusterRole::ConfigServer) {
// Tell the shards to enter phase-1 of setFCV
@@ -537,6 +548,16 @@ private:
dbName,
MODE_X,
[&](const CollectionPtr& collection) {
+ // Fail to downgrade if there exists a collection with
+ // 'changeStreamPreAndPostImages' enabled.
+ // TODO SERVER-61770: Remove once FCV 6.0 becomes last-lts.
+ uassert(ErrorCodes::CannotDowngrade,
+ str::stream() << "Cannot downgrade the cluster as collection "
+ << collection->ns()
+ << " has 'changeStreamPreAndPostImages' enabled",
+ preImagesFeatureFlagDisabledOnDowngradeVersion &&
+ !collection->isChangeStreamPreAndPostImagesEnabled());
+
invariant(collection->getTimeseriesOptions());
auto indexCatalog = collection->getIndexCatalog();
@@ -608,9 +629,30 @@ private:
return true;
},
[&](const CollectionPtr& collection) {
- return collection->getTimeseriesOptions() != boost::none;
+ // TODO SERVER-61770: Remove 'changeStreamPreAndPostImages' check once
+ // FCV 6.0 becomes last-lts.
+ return collection->getTimeseriesOptions() != boost::none ||
+ (preImagesFeatureFlagDisabledOnDowngradeVersion &&
+ collection->isChangeStreamPreAndPostImagesEnabled());
});
}
+
+ // Drop the pre-images collection if 'changeStreamPreAndPostImages' feature flag is not
+ // enabled on the downgrade version.
+ // TODO SERVER-61770: Remove once FCV 6.0 becomes last-lts.
+ if (preImagesFeatureFlagDisabledOnDowngradeVersion) {
+ DropReply dropReply;
+ const auto deletionStatus =
+ dropCollection(opCtx,
+ NamespaceString::kChangeStreamPreImagesNamespace,
+ &dropReply,
+ DropCollectionSystemCollectionMode::kAllowSystemCollectionDrops);
+ uassert(6023700,
+ str::stream() << "Failed to drop the change stream pre-images collection"
+ << causedBy(deletionStatus.reason()),
+ deletionStatus.isOK() ||
+ deletionStatus.code() == ErrorCodes::NamespaceNotFound);
+ }
}
uassert(ErrorCodes::Error(549181),
diff --git a/src/mongo/db/repl/replication_coordinator_external_state_impl.cpp b/src/mongo/db/repl/replication_coordinator_external_state_impl.cpp
index fdbcc43bb78..b3177b71eba 100644
--- a/src/mongo/db/repl/replication_coordinator_external_state_impl.cpp
+++ b/src/mongo/db/repl/replication_coordinator_external_state_impl.cpp
@@ -42,6 +42,7 @@
#include "mongo/bson/util/bson_extract.h"
#include "mongo/db/auth/authorization_session.h"
#include "mongo/db/catalog/coll_mod.h"
+#include "mongo/db/catalog/create_collection.h"
#include "mongo/db/catalog/database.h"
#include "mongo/db/catalog/database_holder.h"
#include "mongo/db/catalog/local_oplog_info.h"
@@ -60,6 +61,7 @@
#include "mongo/db/kill_sessions_local.h"
#include "mongo/db/logical_time_validator.h"
#include "mongo/db/op_observer.h"
+#include "mongo/db/query/query_feature_flags_gen.h"
#include "mongo/db/repl/always_allow_non_local_writes.h"
#include "mongo/db/repl/bgsync.h"
#include "mongo/db/repl/drop_pending_collection_reaper.h"
@@ -582,6 +584,12 @@ OpTime ReplicationCoordinatorExternalStateImpl::onTransitionToPrimary(OperationC
}
});
+ // Create the pre-images collection if it doesn't exist yet.
+ if (::mongo::feature_flags::gFeatureFlagChangeStreamPreAndPostImages.isEnabled(
+ serverGlobalParams.featureCompatibility)) {
+ createChangeStreamPreImagesCollection(opCtx);
+ }
+
serverGlobalParams.validateFeaturesAsPrimary.store(true);
return opTimeToReturn;