summaryrefslogtreecommitdiff
path: root/jstests/noPassthrough/index_primary_aborts_immediately_on_key_generation_error.js
blob: 4ee561c0d2e20a4cc393856c8dd697194449ff59 (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
/**
 * Tests that an index build on a primary which encounters a key generation error aborts immediately
 * instead of waiting until the commit phase, while a secondary should suppress the error and
 * proceed to the next phase.
 *
 * @tags: [
 *   requires_fcv_71,
 *   requires_replication,
 * ]
 */
(function() {
"use strict";

load('jstests/noPassthrough/libs/index_build.js');
load('jstests/libs/fail_point_util.js');

const rst = new ReplSetTest({
    nodes: [
        {},
        {
            // Disallow elections on secondary.
            rsConfig: {
                priority: 0,
            },
        },
    ]
});
rst.startSet();
rst.initiate();

const primary = rst.getPrimary();

const testDB = primary.getDB('test');
const coll = testDB.getCollection('test');

const secondary = rst.getSecondary();
const secondaryDB = secondary.getDB(testDB.getName());
const secondaryColl = secondaryDB.getCollection('test');

// Avoid optimization on empty colls. Invalid 2dsphere key.
assert.commandWorked(coll.insert(
    {geometry: {type: "Polygon", coordinates: [[[0, 0], [0, 1], [1, 1], [-2, -1], [0, 0]]]}}));

// Set the failpoint after the collection scan phase. It is expected that we never hit this
// failpoint due to the immediate index build failure. If this is hit, it will hang the test
// indefinitely.
const failpointHangAfterScan =
    configureFailPoint(testDB, "hangAfterIndexBuildDumpsInsertsFromBulk");

// Block the primary from actually aborting and replicating the 'abortIndexBuild', to give time for
// the secondary to finish the scan.
const failpointBeforeAbort = configureFailPoint(testDB, "hangIndexBuildBeforeAbortCleanUp");

// The secondary should continue to the next index build phase after suppressing the error.
const failpointHangAfterScanSecondary =
    configureFailPoint(secondaryDB, "hangAfterIndexBuildDumpsInsertsFromBulk");

// Create the index and start the build.
const createIdx = IndexBuildTest.startIndexBuild(
    primary, coll.getFullName(), {geometry: "2dsphere"}, {}, [16755], /*commitQuorum: */ 2);

// At this point the secondary has suppressed the error and will continue to the next phase.
failpointHangAfterScanSecondary.wait();
failpointHangAfterScanSecondary.off();

// Let primary finish the abort.
failpointBeforeAbort.off();

// Wait for the createIndexes command to return.
createIdx();

// The abort reason on primary must be due to the "voteAbortIndexBuild" command from the secondary.
const reasonString = `'voteAbortIndexBuild' received from '${secondary.host}'`;
checkLog.checkContainsOnceJsonStringMatch(testDB, 4656003, "error", reasonString);

// As aborting the build involves interrupting the building thread on which the user op is waiting,
// the user op will return before the primary has actually aborted the build. Waiting for the
// 'createIndexes' command to return does not guarantee that the primary has replicated the abort
// oplog entry, nor that the secondary has applied it.
IndexBuildTest.waitForIndexBuildToStop(testDB);
IndexBuildTest.waitForIndexBuildToStop(secondaryDB);

// Assert index does not exist.
IndexBuildTest.assertIndexes(coll, 1, ['_id_'], []);
IndexBuildTest.assertIndexes(secondaryColl, 1, ['_id_'], []);

rst.stopSet();
})();