summaryrefslogtreecommitdiff
path: root/jstests/noPassthrough/timeseries_retry_delete_and_update.js
blob: 276dcb0449f9a0019da15592608f8a6c71acec6a (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
/**
 * Tests retrying of time-series delete and update operations that are eligible for retryable writes
 * (specifically single deletes and updates).
 *
 * @tags: [
 *   requires_replication,
 *   requires_timeseries,
 *   requires_fcv_70,
 * ]
 */
(function() {
'use strict';

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

const primary = rst.getPrimary();

const timeFieldName = 'time';
const metaFieldName = 'tag';
const dateTime = ISODate("2021-07-12T16:00:00Z");
let collCount = 0;

let retriedCommandsCount = 0;
let retriedStatementsCount = 0;

/**
 * Verifies that a timeseries delete or update command supports retryable writes. The arguments to
 * this function are an array of documents to insert initially, a command builder function that
 * returns the command object given the collection to run it on, and a validate function that
 * validates the result after the command has been applied to the collection.
 */
const runTest = function(initialDocs, cmdBuilderFn, validateFn) {
    const session = primary.startSession({retryWrites: true});
    const testDB = session.getDatabase(jsTestName());

    const coll = testDB.getCollection('timeseres_retry_delete_and_update_' + collCount++);
    coll.drop();
    assert.commandWorked(
        testDB.createCollection(coll.getName(), {timeseries: {timeField: timeFieldName}}));

    assert.commandWorked(testDB.runCommand({
        insert: coll.getName(),
        documents: initialDocs,
        lsid: session.getSessionId(),
        txnNumber: NumberLong(0)
    }));

    // For retryable writes, the server uses 'txnNumber' as the key to look up previously executed
    // operations in the sesssion.
    let cmdObj = cmdBuilderFn(coll);
    cmdObj["lsid"] = session.getSessionId();
    cmdObj["txnNumber"] = NumberLong(1);

    assert.commandWorked(testDB.runCommand(cmdObj), 'Failed to write bucket on first write');
    assert.commandWorked(testDB.runCommand(cmdObj), 'Failed to write bucket on retry write');

    validateFn(coll);

    const transactionsServerStatus = testDB.serverStatus().transactions;
    assert.eq(++retriedCommandsCount,
              transactionsServerStatus.retriedCommandsCount,
              'Incorrect statistic in db.serverStatus(): ' + tojson(transactionsServerStatus));
    assert.eq(++retriedStatementsCount,
              transactionsServerStatus.retriedStatementsCount,
              'Incorrect statistic in db.serverStatus(): ' + tojson(transactionsServerStatus));

    session.endSession();
};

const allDocumentsSameBucket = [
    {[timeFieldName]: dateTime, [metaFieldName]: "A", f: 100},
    {[timeFieldName]: dateTime, [metaFieldName]: "A", f: 101},
    {[timeFieldName]: dateTime, [metaFieldName]: "A", f: 102},
];
const allDocumentsDifferentBuckets = [
    {[timeFieldName]: dateTime, [metaFieldName]: "A", f: 100},
    {[timeFieldName]: dateTime, [metaFieldName]: "B", f: 101},
    {[timeFieldName]: dateTime, [metaFieldName]: "C", f: 102},
];

function deleteCmdBuilderFn(coll) {
    return {delete: coll.getName(), deletes: [{q: {}, limit: 1}]};
}
function deleteValidateFn(coll) {
    assert.eq(coll.countDocuments({}), 2, "Expected exactly one document to be deleted.");
}

(function testPartialBucketDelete() {
    runTest(allDocumentsSameBucket, deleteCmdBuilderFn, deleteValidateFn);
})();
(function testFullBucketDelete() {
    runTest(allDocumentsDifferentBuckets, deleteCmdBuilderFn, deleteValidateFn);
})();

function updateCmdBuilderFn(coll) {
    return {update: coll.getName(), updates: [{q: {}, u: {$inc: {updated: 1}}, multi: false}]};
}
function updateValidateFn(coll) {
    assert.eq(coll.countDocuments({updated: {$exists: true}}),
              1,
              "Expected exactly one document to be updated.");
    assert.eq(coll.countDocuments({updated: 1}), 1, "Expected document to be updated only once.");
}

// TODO SERVER-73726 Enable update tests.
// (function testPartialBucketUpdate() {
//     runTest(allDocumentsSameBucket, updateCmdBuilderFn, updateValidateFn);
// })();
// (function testFullBucketUpdate() {
//     runTest(allDocumentsDifferentBuckets, updateCmdBuilderFn, updateValidateFn);
// })();

rst.stopSet();
})();