summaryrefslogtreecommitdiff
path: root/jstests/replsets/tenant_migration_recipient_directly_deletes_its_state_doc.js
blob: 6f6e7e360a274869743be9af97d2228b5fc2ff70 (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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/**
 * Tests that a tenant migration recipient instance shows up as active in serverStatus metrics until
 * it has directly deleted its state doc (even if the state doc has actually already been deleted by
 * the TTL monitor).
 *
 * @tags: [
 *   incompatible_with_macos,
 *   incompatible_with_windows_tls,
 *   # Uses pauseTenantMigrationRecipientBeforeDeletingStateDoc failpoint, which was added in 6.2
 *   requires_fcv_62,
 *   requires_majority_read_concern,
 *   requires_persistence,
 *   serverless,
 * ]
 */

import {TenantMigrationTest} from "jstests/replsets/libs/tenant_migration_test.js";
load("jstests/libs/fail_point_util.js");
load("jstests/libs/uuid_util.js");

(() => {
    jsTest.log("Test case where the TTL monitor deletes the state doc first");

    const tmt = new TenantMigrationTest({name: jsTestName(), quickGarbageCollection: true});

    const recipientPrimary = tmt.getRecipientPrimary();
    const fp =
        configureFailPoint(recipientPrimary, "pauseTenantMigrationRecipientBeforeDeletingStateDoc");

    jsTest.log("Confirm serverStatus does not show any active or completed tenant migrations.");
    let recipientStats = tmt.getTenantMigrationStats(recipientPrimary);
    jsTest.log("recipientStats: " + tojson(recipientStats));
    assert.eq(0, recipientStats.currentMigrationsReceiving);

    jsTest.log("Start a tenant migration.");
    const tenantId = ObjectId().str;
    const migrationId = extractUUIDFromObject(UUID());
    const migrationOpts = {
        migrationIdString: migrationId,
        tenantId: tenantId,
        recipientConnString: tmt.getRecipientConnString(),
    };

    TenantMigrationTest.assertCommitted(tmt.runMigration(migrationOpts));

    jsTest.log("Wait for the migration to reach the failpoint before deleting the state doc.");
    fp.wait();

    jsTest.log("Confirm the state doc has been deleted by the TTL monitor");
    assert.soon(() => {
        return 0 ==
            recipientPrimary.getDB("config").getCollection("tenantMigrationRecipients").count();
    });

    jsTest.log("Confirm the instance still shows up as active in serverStatus.");
    recipientStats = tmt.getTenantMigrationStats(recipientPrimary);
    jsTest.log("recipientStats: " + tojson(recipientStats));
    assert.eq(1, recipientStats.currentMigrationsReceiving);

    // TODO (SERVER-61717): Confirm the instance still shows up in the POS map. Currently, the
    // instance is removed from the map as soon as its' state doc is deleted by the TTL monitor.

    jsTest.log("Turn off the failpoint.");
    fp.off();

    jsTest.log("Confirm the instance eventually stops showing up as active in serverStatus");
    assert.soon(() => {
        recipientStats = tmt.getTenantMigrationStats(recipientPrimary);
        return 0 == recipientStats.currentMigrationsReceiving;
    });

    // TODO (SERVER-61717): Confirm the instance eventually stops showing up in the POS map.

    tmt.stop();
})();

(() => {
    jsTest.log("Test case where the instance deletes the state doc first");

    const tmt = new TenantMigrationTest({name: jsTestName(), quickGarbageCollection: true});

    const recipientPrimary = tmt.getRecipientPrimary();

    jsTest.log("Confirm the TTL index exists");
    const listIndexesRes1 = assert.commandWorked(
        recipientPrimary.getDB("config").runCommand({listIndexes: "tenantMigrationRecipients"}));
    assert(listIndexesRes1.cursor.firstBatch.some(
        elem => elem.name === "TenantMigrationRecipientTTLIndex" && elem.key.expireAt === 1));

    jsTest.log("Drop the TTL index");
    assert.commandWorked(recipientPrimary.getDB("config").runCommand(
        {dropIndexes: "tenantMigrationRecipients", index: "TenantMigrationRecipientTTLIndex"}));

    jsTest.log("Confirm the TTL index no longer exists");
    const listIndexesRes2 = assert.commandWorked(
        recipientPrimary.getDB("config").runCommand({listIndexes: "tenantMigrationRecipients"}));
    assert(listIndexesRes2.cursor.firstBatch.every(elem => elem.key.expireAt == null));

    jsTest.log("Confirm serverStatus does not show any active or completed tenant migrations.");
    let recipientStats = tmt.getTenantMigrationStats(recipientPrimary);
    jsTest.log("recipientStats: " + tojson(recipientStats));
    assert.eq(0, recipientStats.currentMigrationsReceiving);

    jsTest.log("Start a tenant migration.");
    const tenantId = ObjectId().str;
    const migrationId = extractUUIDFromObject(UUID());
    const migrationOpts = {
        migrationIdString: migrationId,
        tenantId: tenantId,
        recipientConnString: tmt.getRecipientConnString(),
    };
    TenantMigrationTest.assertCommitted(tmt.runMigration(migrationOpts));

    jsTest.log("Wait for the instance to delete the state doc");
    assert.soon(() => {
        return 0 ==
            recipientPrimary.getDB("config").getCollection("tenantMigrationRecipients").count();
    });

    jsTest.log("Confirm the instance eventually stops showing up as active in serverStatus");
    assert.soon(() => {
        recipientStats = tmt.getTenantMigrationStats(recipientPrimary);
        return 0 == recipientStats.currentMigrationsReceiving;
    });

    // TODO (SERVER-61717): Confirm the instance eventually stops showing up in the POS map.

    tmt.stop();
})();