summaryrefslogtreecommitdiff
path: root/jstests/serverless/shard_split_concurrent_reads_on_donor_committed.js
diff options
context:
space:
mode:
Diffstat (limited to 'jstests/serverless/shard_split_concurrent_reads_on_donor_committed.js')
-rw-r--r--jstests/serverless/shard_split_concurrent_reads_on_donor_committed.js128
1 files changed, 128 insertions, 0 deletions
diff --git a/jstests/serverless/shard_split_concurrent_reads_on_donor_committed.js b/jstests/serverless/shard_split_concurrent_reads_on_donor_committed.js
new file mode 100644
index 00000000000..16e16799fe6
--- /dev/null
+++ b/jstests/serverless/shard_split_concurrent_reads_on_donor_committed.js
@@ -0,0 +1,128 @@
+/**
+ * Tests that the donor
+ * - rejects reads with atClusterTime/afterClusterTime >= blockTimestamp reads and linearizable
+ * reads after the split commits.
+ *
+ * @tags: [
+ * incompatible_with_eft,
+ * incompatible_with_macos,
+ * incompatible_with_windows_tls,
+ * requires_majority_read_concern,
+ * requires_persistence,
+ * serverless,
+ * requires_fcv_52,
+ * featureFlagShardSplit
+ * ]
+ */
+
+(function() {
+'use strict';
+
+load("jstests/libs/fail_point_util.js");
+load("jstests/libs/parallelTester.js");
+load("jstests/libs/uuid_util.js");
+load("jstests/serverless/libs/basic_serverless_test.js");
+load("jstests/serverless/shard_split_concurrent_reads_on_donor_util.js");
+
+const kCollName = "testColl";
+const kTenantDefinedDbName = "0";
+
+/**
+ * Tests that after the split commits, the donor rejects linearizable reads and reads with
+ * atClusterTime/afterClusterTime >= blockTimestamp.
+ */
+let countTenantMigrationCommittedErrorsPrimary = 0;
+let countTenantMigrationCommittedErrorsSecondaries = 0;
+function testRejectReadsAfterMigrationCommitted(testCase, primary, dbName, collName, migrationId) {
+ const donorDoc = findSplitOperation(primary, migrationId);
+
+ let nodes = [primary];
+ if (testCase.isSupportedOnSecondaries) {
+ nodes = donorRst.nodes;
+
+ if (testCase.requiresReadTimestamp) {
+ countTenantMigrationCommittedErrorsSecondaries += 2;
+ } else {
+ countTenantMigrationCommittedErrorsSecondaries += 1;
+ }
+ }
+
+ if (testCase.requiresReadTimestamp) {
+ countTenantMigrationCommittedErrorsPrimary += 2;
+ } else {
+ countTenantMigrationCommittedErrorsPrimary += 1;
+ }
+
+ nodes.forEach(node => {
+ const db = node.getDB(dbName);
+ if (testCase.requiresReadTimestamp) {
+ runCommandForConcurrentReadTest(db,
+ testCase.command(collName, donorDoc.blockTimestamp),
+ ErrorCodes.TenantMigrationCommitted,
+ testCase.isTransaction);
+ runCommandForConcurrentReadTest(
+ db,
+ testCase.command(collName, donorDoc.commitOrAbortOpTime.ts),
+ ErrorCodes.TenantMigrationCommitted,
+ testCase.isTransaction);
+ } else {
+ runCommandForConcurrentReadTest(db,
+ testCase.command(collName),
+ ErrorCodes.TenantMigrationCommitted,
+ testCase.isTransaction);
+ }
+ });
+}
+
+const testCases = shardSplitConcurrentReadTestCases;
+
+const test = new BasicServerlessTest({
+ recipientTagName: "recipientTag",
+ recipientSetName: "recipientSet",
+ quickGarbageCollection: true
+});
+test.addRecipientNodes();
+
+const tenantId = "tenantId";
+
+let donorRst = test.donor;
+const donorPrimary = test.getDonorPrimary();
+
+// Force the donor to preserve all snapshot history to ensure that transactional reads do not
+// fail with TransientTransactionError "Read timestamp is older than the oldest available
+// timestamp".
+donorRst.nodes.forEach(node => {
+ configureFailPoint(node, "WTPreserveSnapshotHistoryIndefinitely");
+});
+
+const operation = test.createSplitOperation([tenantId]);
+assert.commandWorked(operation.commit());
+
+test.removeRecipientNodesFromDonor();
+
+// Wait for the last oplog entry on the primary to be visible in the committed snapshot view of
+// the oplog on all the secondaries. This is to ensure that snapshot reads on secondaries with
+// unspecified atClusterTime have read timestamp >= commitTimestamp.
+donorRst.awaitLastOpCommitted();
+
+for (const [testCaseName, testCase] of Object.entries(testCases)) {
+ jsTest.log(`Testing inCommitted with testCase ${testCaseName}`);
+ const dbName = `${tenantId}_${testCaseName}-inCommitted-${kTenantDefinedDbName}`;
+ testRejectReadsAfterMigrationCommitted(
+ testCase, donorPrimary, dbName, kCollName, operation.migrationId);
+}
+
+// check on primary
+BasicServerlessTest.checkShardSplitAccessBlocker(donorPrimary, tenantId, {
+ numTenantMigrationCommittedErrors: countTenantMigrationCommittedErrorsPrimary
+});
+let secondaries = donorRst.getSecondaries();
+// check on secondaries
+secondaries.forEach(node => {
+ BasicServerlessTest.checkShardSplitAccessBlocker(node, tenantId, {
+ numTenantMigrationCommittedErrors: countTenantMigrationCommittedErrorsSecondaries
+ });
+});
+
+test.stop();
+})();