diff options
author | Christopher Caplinger <christopher.caplinger@mongodb.com> | 2022-10-21 15:16:01 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-10-21 15:53:56 +0000 |
commit | 9570d902706a9a1c456e1a6d78b555a92fbd23dc (patch) | |
tree | a7590234c777c126b9e9de1037712b6dd19a02b8 /jstests/replsets | |
parent | 0e33e36423a56a0fa63b5cd393ed86a699d07ebc (diff) | |
download | mongo-9570d902706a9a1c456e1a6d78b555a92fbd23dc.tar.gz |
SERVER-67240: Fix TTL Monitor Race with Shard Merge
Diffstat (limited to 'jstests/replsets')
-rw-r--r-- | jstests/replsets/tenant_migration_recipient_shard_merge_ttl.js | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/jstests/replsets/tenant_migration_recipient_shard_merge_ttl.js b/jstests/replsets/tenant_migration_recipient_shard_merge_ttl.js new file mode 100644 index 00000000000..5025167c54c --- /dev/null +++ b/jstests/replsets/tenant_migration_recipient_shard_merge_ttl.js @@ -0,0 +1,106 @@ +/** + * Tests that TTL indexes on the donor are migrated to the recipient and cleanup + * happens as expected for shard merge. + * + * @tags: [ + * incompatible_with_macos, + * incompatible_with_windows_tls, + * requires_majority_read_concern, + * requires_persistence, + * serverless, + * featureFlagShardMerge, + * ] + */ + +(function() { +"use strict"; + +load("jstests/libs/fail_point_util.js"); +load("jstests/libs/uuid_util.js"); +load("jstests/replsets/libs/tenant_migration_test.js"); +load("jstests/replsets/libs/tenant_migration_util.js"); + +const tenantMigrationTest = + new TenantMigrationTest({name: jsTestName(), quickGarbageCollection: true}); + +const recipientPrimary = tenantMigrationTest.getRecipientPrimary(); + +// Note: including this explicit early return here due to the fact that multiversion +// suites will execute this test without featureFlagShardMerge enabled (despite the +// presence of the featureFlagShardMerge tag above), which means the test will attempt +// to run a multi-tenant migration and fail. +if (!TenantMigrationUtil.isShardMergeEnabled(recipientPrimary.getDB("admin"))) { + tenantMigrationTest.stop(); + jsTestLog("Skipping Shard Merge-specific test"); + return; +} + +const tenantId = "testTenantId"; +const tenantDB = tenantMigrationTest.tenantDB(tenantId, "DB"); +const collName = "testColl"; + +const donorPrimary = tenantMigrationTest.getDonorPrimary(); + +const expireAfterSeconds = 1; +donorPrimary.getDB(tenantDB)[collName].insertOne({name: "deleteMe", lastModifiedDate: new Date()}); +donorPrimary.getDB(tenantDB)[collName].createIndex({"lastModifiedDate": 1}, {expireAfterSeconds}); + +const hangTTLCollectionCacheAfterRegisteringInfo = + configureFailPoint(recipientPrimary, "hangTTLCollectionCacheAfterRegisteringInfo"); +let hangTTLMonitorBetweenPasses = + configureFailPoint(recipientPrimary, "hangTTLMonitorBetweenPasses"); + +// Pause before TTL on the donor to prevent test documents from being cleaned up before migration. +const waitForTTLPassOnDonor = configureFailPoint(donorPrimary, "hangTTLMonitorBetweenPasses"); + +const migrationUuid = UUID(); +const migrationOpts = { + migrationIdString: extractUUIDFromObject(migrationUuid), + readPreference: {mode: 'primary'} +}; + +assert.commandWorked(tenantMigrationTest.startMigration(migrationOpts)); + +// Wait for a TTL pass to start on the Recipient and then block before continuing. +hangTTLMonitorBetweenPasses.wait(); + +// Wait until we've registered our TTL index in the cache, but block before committing +// the collection in the catalog. +hangTTLCollectionCacheAfterRegisteringInfo.wait(); + +// Wait for TTL expiry. +sleep(expireAfterSeconds * 1000); + +// Unblock the TTL pass on the recipient to let it clean up. +hangTTLMonitorBetweenPasses.off(); + +// Wait for a full TTL cycle to complete in order to ensure that the TTL cache entry for the +// collection (which does not yet have an entry in the collection catalog) is not deregistered. We +// skip the first pass because it's possible that we can turn off the failpoint and then re-enable +// before the TTL machinery is actually unblocked. +hangTTLMonitorBetweenPasses = + configureFailPoint(recipientPrimary, "hangTTLMonitorBetweenPasses", {}, {skip: 1}); +hangTTLMonitorBetweenPasses.wait(); + +// Unblock TTL registration, thus allowing the collection to be registered in the catalog. +hangTTLCollectionCacheAfterRegisteringInfo.off(); + +hangTTLMonitorBetweenPasses.off(); + +TenantMigrationTest.assertCommitted(tenantMigrationTest.waitForMigrationToComplete(migrationOpts)); +assert.commandWorked(tenantMigrationTest.forgetMigration(migrationOpts.migrationIdString)); +tenantMigrationTest.waitForMigrationGarbageCollection(migrationOpts); + +// Wait for another full TTL pass after the migration completes to ensure we have given the document +// a chance to be deleted. +hangTTLMonitorBetweenPasses = + configureFailPoint(recipientPrimary, "hangTTLMonitorBetweenPasses", {}, {skip: 1}); +hangTTLMonitorBetweenPasses.wait(); + +const documentCount = recipientPrimary.getDB(tenantDB)[collName].countDocuments({name: "deleteMe"}); +assert.eq(documentCount, 0); + +hangTTLMonitorBetweenPasses.off(); + +tenantMigrationTest.stop(); +})(); |