summaryrefslogtreecommitdiff
path: root/jstests/replsets/tenant_migration_transaction_boundary.js
blob: d3e886025553ac613d511305dcbae510a4029d1c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
/**
 * Test a (non-prepared) large-format committed transaction T, with at least one oplog entry before
 * startFetchingDonorOpTime, and a commit OpTime between startFetchingDonorOpTime and
 * startApplyingAfterOpTime.
 *
 *                                     Donor Oplog
 *        *-------------------*-------------------*-------------------*
 *   T applyOps entry    startFetching       T commit entry      startApplying
 *                                                |
 *        <-------------- prevOpTime -------------*
 *
 * The recipient doesn't need to recover T's oplog chain, since T committed before startApplying,
 * and trying to recover T would fail because the recipient didn't fetch T's oldest entries.
 *
 * @tags: [
 *   incompatible_with_eft,
 *   incompatible_with_macos,
 *   incompatible_with_windows_tls,
 *   requires_majority_read_concern,
 *   requires_persistence,
 *   serverless,
 * ]
 */

(function() {
"use strict";

load("jstests/replsets/libs/tenant_migration_test.js");
load("jstests/replsets/libs/tenant_migration_util.js");
load("jstests/replsets/rslib.js");
load("jstests/libs/uuid_util.js");

const tenantMigrationTest = new TenantMigrationTest({name: jsTestName()});

const tenantId = "testTenantId";
const tenantDB = tenantMigrationTest.tenantDB(tenantId, "testDB");
const collName = "testColl";
const tenantNS = `${tenantDB}.${collName}`;
const transactionsNS = "config.transactions";

const donorPrimary = tenantMigrationTest.getDonorPrimary();
const recipientPrimary = tenantMigrationTest.getRecipientPrimary();

jsTestLog("Running a migration");
const migrationId = UUID();
const migrationOpts = {
    migrationIdString: extractUUIDFromObject(migrationId),
    tenantId,
};

jsTestLog("Hang just before getting start opTimes from donor");
let fp =
    configureFailPoint(recipientPrimary, "fpAfterComparingRecipientAndDonorFCV", {action: "hang"});
tenantMigrationTest.startMigration(migrationOpts);

fp.wait();

{
    // This transaction will straddle startFetching - the oplog entry for the commit will have a
    // timestamp equal to startFetching, and previous entries will have timestamps earlier than it.
    jsTestLog("Run and commit a transaction prior to the migration");
    const session = donorPrimary.startSession({causalConsistency: false});
    const sessionDb = session.getDatabase(tenantDB);
    const sessionColl = sessionDb.getCollection(collName);

    function makeLargeDoc(numMB) {
        return {x: new Array(numMB * 1024 * 1024).join('A')};
    }

    session.startTransaction();
    sessionColl.insert({doc: makeLargeDoc(10)});
    sessionColl.insert({doc: makeLargeDoc(5)});
    sessionColl.insert({doc: makeLargeDoc(5)});
    let commitRes = session.commitTransaction_forTesting();
    assert.eq(1, commitRes.ok);
    session.endSession();
}

jsTestLog("LastWriteOpTime of transaction is " +
          tojson(donorPrimary.getCollection(transactionsNS)
                     .find({}, {"_id": -1, "lastWriteOpTime": 1})
                     .toArray()));

fp.off();
TenantMigrationTest.assertCommitted(tenantMigrationTest.waitForMigrationToComplete(migrationOpts));
assert.eq(recipientPrimary.getCollection(tenantNS).countDocuments({}), 3);
assert.eq(recipientPrimary.getCollection(tenantNS).count(), 3);
tenantMigrationTest.stop();
})();