summaryrefslogtreecommitdiff
path: root/jstests/replsets/libs/apply_ops_insert_write_conflict.js
blob: 4cbdbe18e88546fcbf20a8f651e15e0304a6595e (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
/**
 * Sets up a test for WriteConflictException handling in applyOps with an insert workload.
 */
var ApplyOpsInsertWriteConflictTest = function(options) {
    'use strict';

    // Skip db hash check because this test may throw write conflicts and collmod fails.
    TestData.skipCheckDBHashes = true;

    if (!(this instanceof ApplyOpsInsertWriteConflictTest)) {
        return new ApplyOpsInsertWriteConflictTest(options);
    }

    // Capture the 'this' reference
    var self = this;

    self.options = options;

    /**
     * Runs the test.
     */
    this.run = function() {
        var options = this.options;

        var replTest = new ReplSetTest({nodes: 1});
        replTest.startSet();
        replTest.initiate();

        var primary = replTest.getPrimary();
        var primaryDB = primary.getDB('test');

        var t = primaryDB.getCollection(options.testName);
        t.drop();

        assert.commandWorked(primaryDB.createCollection(t.getName()));

        var numOps = 1000;
        var ops = Array(numOps).fill('ignored').map((unused, i) => {
            return {op: 'i', ns: t.getFullName(), o: {_id: i}};
        });

        // Probabilities for WCE are chosen based on empirical testing.
        // The probability for WCE during an atomic applyOps should be much smaller than that for
        // the non-atomic case because we have to attempt to re-apply the entire batch of 'numOps'
        // operations on WCE in the atomic case.
        var probability = (options.atomic ? 0.1 : 5.0) / numOps;

        // Set up failpoint to trigger WriteConflictException during write operations.
        assert.commandWorked(
            primaryDB.adminCommand({setParameter: 1, traceWriteConflictExceptions: true}));
        assert.commandWorked(primaryDB.adminCommand({
            configureFailPoint: 'WTWriteConflictException',
            mode: {activationProbability: probability}
        }));

        // This logs each operation being applied.
        var previousLogLevel =
            assert.commandWorked(primaryDB.setLogLevel(3, 'replication')).was.replication.verbosity;

        var applyOpsResult = primaryDB.adminCommand({applyOps: ops, allowAtomic: options.atomic});

        // Reset log level.
        primaryDB.setLogLevel(previousLogLevel, 'replication');

        assert.eq(
            numOps,
            applyOpsResult.applied,
            'number of operations applied did not match list of generated insert operations. ' +
                'applyOps result: ' + tojson(applyOpsResult));
        applyOpsResult.results.forEach((operationSucceeded, i) => {
            assert(operationSucceeded,
                   'applyOps failed: operation with index ' + i + ' failed: operation: ' +
                       tojson(ops[i], '', true) + '. applyOps result: ' + tojson(applyOpsResult));
        });
        assert.commandWorked(applyOpsResult);

        replTest.stopSet();
    };
};