summaryrefslogtreecommitdiff
path: root/jstests/replsets/replSetGetStatus_member_wall_times.js
blob: 9663dae54fe8a55a3f83fbf868dcb55d58d1b027 (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 replSetGetStatus responses include the last applied and durable wall times for other
 * members.
 *
 * @tags: [multiversion_incompatible]
 */

(function() {
"use strict";
load("jstests/libs/write_concern_util.js");
load("jstests/replsets/rslib.js");

// We use GTE to account for the possibility of other writes in the system (e.g. HMAC).
// Comparison is GTE by default, GT if 'strict' is specified.
function checkWallTimes(primary, greaterMemberIndex, lesserMemberIndex, strict = false) {
    assert.soonNoExcept(function() {
        let res = assert.commandWorked(primary.adminCommand({replSetGetStatus: 1}));
        assert(res.members, () => tojson(res));

        const greater = res.members[greaterMemberIndex];
        assert(greater, () => tojson(res));
        const greaterApplied = greater.lastAppliedWallTime;
        const greaterDurable = greater.lastAppliedWallTime;
        assert(greaterApplied, () => tojson(res));
        assert(greaterDurable, () => tojson(res));

        const lesser = res.members[lesserMemberIndex];
        assert(lesser, () => tojson(res));
        const lesserApplied = lesser.lastAppliedWallTime;
        const lesserDurable = lesser.lastDurableWallTime;
        assert(lesser.lastAppliedWallTime, () => tojson(res));
        assert(lesser.lastDurableWallTime, () => tojson(res));

        if (!strict) {
            assert.gte(greaterApplied, lesserApplied, () => tojson(res));
            assert.gte(greaterDurable, lesserDurable, () => tojson(res));
        } else {
            assert.gt(greaterApplied, lesserApplied, () => tojson(res));
            assert.gt(greaterDurable, lesserDurable, () => tojson(res));
        }

        return true;
    });
}

const name = jsTestName();
const rst = new ReplSetTest({name: name, nodes: 3, settings: {chainingAllowed: false}});

rst.startSet();
rst.initiateWithHighElectionTimeout();
rst.awaitReplication();

const primary = rst.getPrimary();                                   // node 0
const [caughtUpSecondary, laggedSecondary] = rst.getSecondaries();  // nodes 1 and 2

const dbName = "testdb";
const collName = "testcoll";
const primaryDB = primary.getDB(dbName);
const primaryColl = primaryDB.getCollection(collName);

jsTestLog("Creating test collection");
assert.commandWorked(primaryColl.insert({"one": 1}));
rst.awaitReplication();

checkWallTimes(primary, 0 /* greater */, 1 /* lesser */);
checkWallTimes(primary, 0 /* greater */, 2 /* lesser */);

jsTestLog("Stopping replication on secondary: " + laggedSecondary.host);
stopServerReplication(laggedSecondary);

jsTestLog("Adding more documents to collection");
assert.commandWorked(primaryColl.insert({"two": 2}, {writeConcern: {w: 1}}));
rst.awaitReplication(
    undefined /* timeout */, undefined /* secondaryOpTimeType */, [caughtUpSecondary]);

// Wall times of the lagged secondary should be strictly lesser.
checkWallTimes(primary, 0 /* greater */, 2 /* lesser */, true /* strict */);
checkWallTimes(primary, 1 /* greater */, 2 /* lesser */, true /* strict */);

jsTestLog("Letting lagged secondary catch up");
restartServerReplication(laggedSecondary);
rst.awaitReplication();

checkWallTimes(primary, 0 /* greater */, 1 /* lesser */);
checkWallTimes(primary, 0 /* greater */, 2 /* lesser */);

rst.stopSet();
})();