summaryrefslogtreecommitdiff
path: root/jstests
diff options
context:
space:
mode:
authorSuganthi Mani <38441312+smani87@users.noreply.github.com>2022-02-15 18:48:08 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-02-25 15:18:03 +0000
commit71d70bf5ebba88a8f51a20d660cb4d9c6532f35c (patch)
tree48eec8abe846ab67135ac9a11e92a4b06b235e13 /jstests
parent455957ee90136e70ec93df6bdf26b118cc42b5b2 (diff)
downloadmongo-71d70bf5ebba88a8f51a20d660cb4d9c6532f35c.tar.gz
SERVER-63129 Tenant collection cloner resume should ignore “view already exists” errors while creating collections.r5.3.0-rc2
(cherry picked from commit e840bb65779035e3f5e7d1fb9b6951c291957a74)
Diffstat (limited to 'jstests')
-rw-r--r--jstests/replsets/tenant_migration_resume_collection_cloner_after_recipient_failover_with_dropped_views.js136
1 files changed, 136 insertions, 0 deletions
diff --git a/jstests/replsets/tenant_migration_resume_collection_cloner_after_recipient_failover_with_dropped_views.js b/jstests/replsets/tenant_migration_resume_collection_cloner_after_recipient_failover_with_dropped_views.js
new file mode 100644
index 00000000000..70c422dacf8
--- /dev/null
+++ b/jstests/replsets/tenant_migration_resume_collection_cloner_after_recipient_failover_with_dropped_views.js
@@ -0,0 +1,136 @@
+/**
+ * Tests that in tenant migration, the collection recreated on a dropped view namespace is handled
+ * correctly on resuming the logical tenant collection cloning phase due to recipient failover.
+ * @tags: [
+ * incompatible_with_eft,
+ * incompatible_with_macos,
+ * incompatible_with_shard_merge,
+ * incompatible_with_windows_tls,
+ * requires_majority_read_concern,
+ * requires_persistence,
+ * serverless,
+ * ]
+ */
+
+(function() {
+"use strict";
+
+const tenantMigrationFailoverTest = function(isTimeSeries, createCollFn) {
+ load("jstests/libs/fail_point_util.js");
+ load("jstests/libs/uuid_util.js"); // for 'extractUUIDFromObject'
+ load("jstests/replsets/libs/tenant_migration_test.js");
+ load("jstests/replsets/libs/tenant_migration_util.js");
+
+ const recipientRst = new ReplSetTest({
+ nodes: 2,
+ name: jsTestName() + "_recipient",
+ nodeOptions: Object.assign(TenantMigrationUtil.makeX509OptionsForTest().recipient, {
+ setParameter: {
+ // Allow reads on recipient before migration completes for testing.
+ 'failpoint.tenantMigrationRecipientNotRejectReads': tojson({mode: 'alwaysOn'}),
+ }
+ })
+ });
+
+ recipientRst.startSet();
+ recipientRst.initiate();
+
+ const tenantMigrationTest =
+ new TenantMigrationTest({name: jsTestName(), recipientRst: recipientRst});
+
+ const donorRst = tenantMigrationTest.getDonorRst();
+ const donorPrimary = donorRst.getPrimary();
+
+ const tenantId = "testTenantId";
+ const dbName = tenantMigrationTest.tenantDB(tenantId, "testDB");
+ const donorDB = donorPrimary.getDB(dbName);
+ const collName = "testColl";
+ const donorColl = donorDB[collName];
+
+ let getCollectionInfo = function(conn) {
+ return conn.getDB(dbName).getCollectionInfos().filter(coll => {
+ return coll.name === collName;
+ });
+ };
+
+ // Create a timeseries collection or a regular view.
+ assert.commandWorked(createCollFn(donorDB, collName));
+ donorRst.awaitReplication();
+
+ const migrationId = UUID();
+ const migrationIdString = extractUUIDFromObject(migrationId);
+ const migrationOpts = {
+ migrationIdString: migrationIdString,
+ recipientConnString: tenantMigrationTest.getRecipientConnString(),
+ tenantId: tenantId,
+ };
+
+ const recipientPrimary = recipientRst.getPrimary();
+ const recipientDb = recipientPrimary.getDB(dbName);
+ const recipientSystemViewsColl = recipientDb.getCollection("system.views");
+
+ // Configure a fail point to have the recipient primary hang after cloning
+ // "testTenantId_testDB.system.views" collection.
+ const hangDuringCollectionClone =
+ configureFailPoint(recipientPrimary,
+ "tenantMigrationHangCollectionClonerAfterHandlingBatchResponse",
+ {nss: recipientSystemViewsColl.getFullName()});
+
+ // Start the migration and wait for the migration to hang after cloning
+ // "testTenantId_testDB.system.views" collection.
+ assert.commandWorked(tenantMigrationTest.startMigration(migrationOpts));
+ hangDuringCollectionClone.wait();
+
+ assert.soon(() => recipientSystemViewsColl.find().itcount() >= 1);
+ recipientRst.awaitLastOpCommitted();
+ const newRecipientPrimary = recipientRst.getSecondaries()[0];
+
+ // Verify that a view has been registered for "testTenantId_testDB.testColl" on the new
+ // recipient primary.
+ let collectionInfo = getCollectionInfo(newRecipientPrimary);
+ assert.eq(1, collectionInfo.length);
+ assert(collectionInfo[0].type === (isTimeSeries ? "timeseries" : "view"),
+ "data store type mismatch: " + tojson(collectionInfo[0]));
+
+ // Drop the view and create a regular collection with the same namespace as the
+ // dropped view on donor.
+ assert(donorColl.drop());
+ assert.commandWorked(donorDB.createCollection(collName));
+
+ // We need to skip TenantDatabaseCloner::listExistingCollectionsStage() to make sure
+ // the recipient always clone the above newly created regular collection after the failover.
+ // Currently, we restart cloning after a failover, only from the collection whose UUID is
+ // greater than or equal to the last collection we have on disk.
+ const skiplistExistingCollectionsStage =
+ configureFailPoint(newRecipientPrimary, "skiplistExistingCollectionsStage");
+
+ // Step up a new node in the recipient set and trigger a failover.
+ recipientRst.stepUp(newRecipientPrimary);
+ hangDuringCollectionClone.off();
+
+ // The migration should go through after recipient failover.
+ TenantMigrationTest.assertCommitted(
+ tenantMigrationTest.waitForMigrationToComplete(migrationOpts));
+
+ // Check that recipient has dropped the view and and re-created the regular collection as part
+ // of migration oplog catchup phase.
+ collectionInfo = getCollectionInfo(newRecipientPrimary);
+ assert.eq(1, collectionInfo.length);
+ assert(collectionInfo[0].type === "collection",
+ "data store type mismatch: " + tojson(collectionInfo[0]));
+
+ tenantMigrationTest.stop();
+ recipientRst.stopSet();
+};
+
+jsTestLog("Running tenant migration test for time-series collection");
+// Creating a timeseries collection, implicity creates a view on the 'collName' collection
+// namespace.
+tenantMigrationFailoverTest(true,
+ (db, collName) => db.createCollection(
+ collName, {timeseries: {timeField: "time", metaField: "bucket"}}));
+
+jsTestLog("Running tenant migration test for regular view");
+tenantMigrationFailoverTest(false,
+ (db, collName) => db.createView(collName, "sourceCollection", []));
+})();