summaryrefslogtreecommitdiff
path: root/jstests/aggregation/bugs/server37750.js
blob: 56b11511accf3a3734a9aa3fdd0891d4e53c2a16 (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
/**
 * Confirms that a sharded $sample which employs the DSSampleFromRandomCursor optimization is
 * capable of yielding.
 *
 * @tags: [assumes_read_concern_unchanged, do_not_wrap_aggregations_in_facets, requires_journaling,
 * requires_sharding]
 */
(function() {
    "use strict";

    load("jstests/libs/fixture_helpers.js");  // For FixtureHelpers.

    // Set up a 2-shard cluster. Configure 'internalQueryExecYieldIterations' on both shards such
    // that operations will yield on each PlanExecuter iteration.
    const st = new ShardingTest({
        name: jsTestName(),
        shards: 2,
        rs: {nodes: 1, setParameter: {internalQueryExecYieldIterations: 1}}
    });

    const mongosDB = st.s.getDB(jsTestName());
    const mongosColl = mongosDB.test;

    // Shard the test collection, split it at {_id: 0}, and move the upper chunk to shard1.
    st.shardColl(mongosColl, {_id: 1}, {_id: 0}, {_id: 0});

    // Insert enough documents on each shard to induce the $sample random-cursor optimization.
    for (let i = (-150); i < 150; ++i) {
        assert.writeOK(mongosColl.insert({_id: i}));
    }

    // Run the initial aggregate for the $sample stage.
    const cmdRes = assert.commandWorked(mongosDB.runCommand({
        aggregate: mongosColl.getName(),
        pipeline: [{$sample: {size: 3}}],
        comment: "$sample random",
        cursor: {batchSize: 0}
    }));
    assert.eq(cmdRes.cursor.firstBatch.length, 0);

    // Force each shard to hang on yield to allow for currentOp capture.
    FixtureHelpers.runCommandOnEachPrimary({
        db: mongosDB.getSiblingDB("admin"),
        cmdObj: {
            configureFailPoint: "setYieldAllLocksHang",
            mode: "alwaysOn",
            data: {namespace: mongosColl.getFullName()}
        }
    });

    // Run $currentOp to confirm that the $sample getMore yields on both shards.
    const awaitShell = startParallelShell(() => {
        load("jstests/libs/fixture_helpers.js");
        assert.soon(() => db.getSiblingDB("admin")
                              .aggregate([
                                  {$currentOp: {}},
                                  {
                                    $match: {
                                        "originatingCommand.comment": "$sample random",
                                        planSummary: "MULTI_ITERATOR",
                                        numYields: {$gt: 0}
                                    }
                                  }
                              ])
                              .itcount() === 2);
        // Release the failpoint and allow the getMores to complete.
        FixtureHelpers.runCommandOnEachPrimary({
            db: db.getSiblingDB("admin"),
            cmdObj: {configureFailPoint: "setYieldAllLocksHang", mode: "off"}
        });
    }, mongosDB.getMongo().port);

    // Retrieve the results for the $sample aggregation.
    const sampleCursor = new DBCommandCursor(mongosDB, cmdRes);
    assert.eq(sampleCursor.toArray().length, 3);

    // Confirm that the parallel shell completes successfully, and tear down the cluster.
    awaitShell();
    st.stop();
})();