summaryrefslogtreecommitdiff
path: root/jstests/noPassthrough/server_transaction_metrics_last_committed_transaction.js
blob: bc083f6ad6751ec016bbec7e0d51bfd1644fde68 (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
// Tests the 'lastCommittedTransaction' serverStatus section.
// @tags: [uses_transactions, uses_prepare_transaction]
(function() {
"use strict";
load("jstests/core/txns/libs/prepare_helpers.js");

const rst = new ReplSetTest({nodes: 1});
rst.startSet();
rst.initiate();
const primary = rst.getPrimary();
assert.commandWorked(primary.adminCommand({setDefaultRWConcern: 1, defaultWriteConcern: {w: 1}}));
let newDefaultWC = {"w": 1, "wtimeout": 0, "provenance": "customDefault"};

const dbName = "test";
const collName = "coll";

const session = primary.getDB(dbName).getMongo().startSession();
const sessionDb = session.getDatabase(dbName);
const sessionColl = sessionDb[collName];
assert.commandWorked(sessionDb.runCommand({create: collName}));

function checkLastCommittedTransaction(operationCount, writeConcern) {
    let res = assert.commandWorked(primary.adminCommand({serverStatus: 1}));
    assert(res.hasOwnProperty("transactions"), () => tojson(res));
    assert(res.transactions.hasOwnProperty("lastCommittedTransaction"),
           () => tojson(res.transactions));
    assert.eq(operationCount,
              res.transactions.lastCommittedTransaction.operationCount,
              () => tojson(res.transactions));
    if (operationCount === 0) {
        assert.eq(0,
                  res.transactions.lastCommittedTransaction.oplogOperationBytes,
                  () => tojson(res.transactions));
    } else {
        assert.lt(0,
                  res.transactions.lastCommittedTransaction.oplogOperationBytes,
                  () => tojson(res.transactions));
    }
    assert.docEq(writeConcern,
                 res.transactions.lastCommittedTransaction.writeConcern,
                 () => tojson(res.transactions));
}

// Initially the 'lastCommittedTransaction' section is not present.
let res = assert.commandWorked(primary.adminCommand({serverStatus: 1}));
assert(res.hasOwnProperty("transactions"), () => tojson(res));
assert(!res.transactions.hasOwnProperty("lastCommittedTransaction"), () => tojson(res));

// Start a transaction. The 'lastCommittedTransaction' section is not yet updated.
session.startTransaction();
assert.commandWorked(sessionColl.insert({}));
res = assert.commandWorked(primary.adminCommand({serverStatus: 1}));
assert(res.hasOwnProperty("transactions"), () => tojson(res));
assert(!res.transactions.hasOwnProperty("lastCommittedTransaction"), () => tojson(res));

// Prepare the transaction. The 'lastCommittedTransaction' section is not yet updated.
let prepareTimestampForCommit = PrepareHelpers.prepareTransaction(session);
res = assert.commandWorked(primary.adminCommand({serverStatus: 1}));
assert(res.hasOwnProperty("transactions"), () => tojson(res));
assert(!res.transactions.hasOwnProperty("lastCommittedTransaction"), () => tojson(res));

// Commit the transaction. The 'lastCommittedTransaction' section should be updated.
assert.commandWorked(PrepareHelpers.commitTransaction(session, prepareTimestampForCommit));
checkLastCommittedTransaction(1, newDefaultWC);

// Check that we are able to exclude 'lastCommittedTransaction'. FTDC uses this to filter out
// the section as it frequently triggers scheme changes.
let filteredRes = assert.commandWorked(
    primary.adminCommand({serverStatus: 1, transactions: {includeLastCommitted: false}}));
assert(!filteredRes.transactions.hasOwnProperty("lastCommittedTransaction"),
       () => tojson(filteredRes));

function runTests(prepare) {
    jsTestLog("Testing server transaction metrics with prepare=" + prepare);

    function commitTransaction() {
        if (prepare) {
            prepareTimestampForCommit = PrepareHelpers.prepareTransaction(session);
            assert.commandWorked(
                PrepareHelpers.commitTransaction(session, prepareTimestampForCommit));
        } else {
            assert.commandWorked(session.commitTransaction_forTesting());
        }
    }

    // Run a transaction with multiple write operations.
    session.startTransaction();
    assert.commandWorked(sessionColl.insert({}));
    assert.commandWorked(sessionColl.insert({}));
    commitTransaction();
    checkLastCommittedTransaction(2, newDefaultWC);

    // Run a read-only transaction.
    session.startTransaction();
    sessionColl.findOne();
    commitTransaction();
    checkLastCommittedTransaction(0, newDefaultWC);

    // Run a transaction with non-default writeConcern.
    session.startTransaction({writeConcern: {w: 1}});
    assert.commandWorked(sessionColl.insert({}));
    commitTransaction();
    checkLastCommittedTransaction(1, {w: 1, wtimeout: 0, provenance: "clientSupplied"});

    // Run a read-only transaction with non-default writeConcern.
    session.startTransaction({writeConcern: {w: "majority"}});
    sessionColl.findOne();
    commitTransaction();
    checkLastCommittedTransaction(0, {w: "majority", wtimeout: 0, provenance: "clientSupplied"});
}

runTests(true /*prepare*/);
runTests(false /*prepare*/);

session.endSession();
rst.stopSet();
}());