diff options
author | Suganthi Mani <38441312+smani87@users.noreply.github.com> | 2022-02-15 18:48:08 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-02-25 15:18:03 +0000 |
commit | 71d70bf5ebba88a8f51a20d660cb4d9c6532f35c (patch) | |
tree | 48eec8abe846ab67135ac9a11e92a4b06b235e13 /jstests | |
parent | 455957ee90136e70ec93df6bdf26b118cc42b5b2 (diff) | |
download | mongo-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.js | 136 |
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", [])); +})(); |