summaryrefslogtreecommitdiff
path: root/jstests/replsets/tenant_migration_conflicting_recipient_sync_data_cmds.js
diff options
context:
space:
mode:
authorSuganthi Mani <suganthi.mani@mongodb.com>2020-09-10 13:59:12 -0400
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-10-19 22:11:30 +0000
commit73010da1fe57e548cf7a651361dbe6eae535b87c (patch)
tree85c967bd487e007a90003df0840f46fbacbf1d87 /jstests/replsets/tenant_migration_conflicting_recipient_sync_data_cmds.js
parent552c3d62daa278ef165c005cc972353860382a44 (diff)
downloadmongo-73010da1fe57e548cf7a651361dbe6eae535b87c.tar.gz
SERVER-48796 Implement recipientSyncData command in MigrationServiceInstance.
Diffstat (limited to 'jstests/replsets/tenant_migration_conflicting_recipient_sync_data_cmds.js')
-rw-r--r--jstests/replsets/tenant_migration_conflicting_recipient_sync_data_cmds.js105
1 files changed, 105 insertions, 0 deletions
diff --git a/jstests/replsets/tenant_migration_conflicting_recipient_sync_data_cmds.js b/jstests/replsets/tenant_migration_conflicting_recipient_sync_data_cmds.js
new file mode 100644
index 00000000000..e9d0208e9e3
--- /dev/null
+++ b/jstests/replsets/tenant_migration_conflicting_recipient_sync_data_cmds.js
@@ -0,0 +1,105 @@
+/**
+ * Test that tenant migration recipient rejects conflicting recipientSyncData commands.
+ *
+ * @tags: [requires_fcv_47, requires_majority_read_concern, incompatible_with_eft]
+ */
+(function() {
+
+"use strict";
+load("jstests/libs/parallel_shell_helpers.js");
+load("jstests/libs/curop_helpers.js"); // for waitForCurOpByFailPoint().
+
+var rst = new ReplSetTest({nodes: 1, nodeOptions: {setParameter: {enableTenantMigrations: true}}});
+rst.startSet();
+rst.initiate();
+
+const primary = rst.getPrimary();
+const configDB = primary.getDB("config");
+const tenantMigrationRecipientStateColl = configDB["tenantMigrationRecipients"];
+const tenantMigrationRecipientStateCollNss = tenantMigrationRecipientStateColl.getFullName();
+
+const tenantId = "test";
+const connectionString = "foo/bar:12345";
+const readPreference = {
+ mode: 'primary'
+};
+
+function checkTenantMigrationRecipientStateCollCount(expectedCount) {
+ let res = tenantMigrationRecipientStateColl.find().toArray();
+ assert.eq(expectedCount,
+ res.length,
+ "'config.tenantMigrationRecipients' collection count mismatch: " + tojson(res));
+}
+
+function startRecipientSyncDataCmd(migrationUuid, tenantId, connectionString, readPreference) {
+ jsTestLog("Starting a recipientSyncDataCmd for migrationUuid: " + migrationUuid +
+ " tenantId: '" + tenantId + "'");
+ assert.commandWorkedOrFailedWithCode(db.adminCommand({
+ recipientSyncData: 1,
+ migrationId: migrationUuid,
+ donorConnectionString: connectionString,
+ tenantId: tenantId,
+ readPreference: readPreference
+ }),
+ ErrorCodes.ConflictingOperationInProgress);
+}
+
+// Enable the failpoint to stop the tenant migration after persisting the state doc.
+assert.commandWorked(primary.adminCommand({
+ configureFailPoint: "fpAfterPersistingTenantMigrationRecipientInstanceStateDoc",
+ mode: "alwaysOn",
+ data: {action: "stop"}
+}));
+
+{
+ // Enable the failpoint before inserting the state document by upsert command.
+ assert.commandWorked(primary.adminCommand(
+ {configureFailPoint: "hangBeforeUpsertPerformsInsert", mode: "alwaysOn"}));
+
+ // Sanity check : 'config.tenantMigrationRecipients' collection count should be empty.
+ checkTenantMigrationRecipientStateCollCount(0);
+
+ // Start the conflicting recipientSyncData cmds.
+ const recipientSyncDataCmd1 = startParallelShell(
+ funWithArgs(startRecipientSyncDataCmd, UUID(), tenantId, connectionString, readPreference),
+ primary.port);
+ const recipientSyncDataCmd2 = startParallelShell(
+ funWithArgs(startRecipientSyncDataCmd, UUID(), tenantId, connectionString, readPreference),
+ primary.port);
+
+ // Wait until both the conflicting instances got started.
+ checkLog.containsWithCount(primary, "Starting tenant migration recipient instance", 2);
+
+ jsTestLog("Waiting for 'hangBeforeUpsertPerformsInsert' failpoint to reach");
+ waitForCurOpByFailPoint(
+ configDB, tenantMigrationRecipientStateCollNss, "hangBeforeUpsertPerformsInsert");
+
+ // Unblock the tenant migration instance from persisting the state doc.
+ assert.commandWorked(
+ primary.adminCommand({configureFailPoint: "hangBeforeUpsertPerformsInsert", mode: "off"}));
+
+ // Wait for both the conflicting instances to complete.
+ recipientSyncDataCmd1();
+ recipientSyncDataCmd2();
+
+ // Only one instance should have succeeded in persisting the state doc, other should have failed
+ // with ErrorCodes.ConflictingOperationInProgress.
+ checkTenantMigrationRecipientStateCollCount(1);
+}
+
+{
+ // Now, again call recipientSyncData cmd to run on the same tenant "test'. Since, our previous
+ // instance for tenant "test' wasn't garbage collected, the migration status for that tenant is
+ // considered as active. So, this command should fail with
+ // ErrorCodes.ConflictingOperationInProgress.
+ const recipientSyncDataCmd3 = startParallelShell(
+ funWithArgs(startRecipientSyncDataCmd, UUID(), tenantId, connectionString, readPreference),
+ primary.port);
+ recipientSyncDataCmd3();
+
+ // Collection count should remain the same.
+ checkTenantMigrationRecipientStateCollCount(1);
+}
+
+rst.stopSet();
+})();