summaryrefslogtreecommitdiff
path: root/jstests/replsets/log_secondary_oplog_application.js
blob: 90a8025a9a128430c3fd9557832a698343a76b8d (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
/**
 * Tests that the server logs ops on the secondary if and only if they are slow to apply.
 * We should only report ops if they take longer than "slowMS" to apply on a secondary.
 * We intentionally target CRUD ops in this test, since we know we should be the only ones
 * issuing them. See below for details on how we simulate quickness and slowness.
 */

(function() {
"use strict";
load("jstests/libs/check_log.js");

let name = "log_secondary_oplog_application";
let rst = ReplSetTest({name: name, nodes: 2});
rst.startSet();

let nodes = rst.nodeList();
rst.initiate({
    "_id": name,
    "members": [{"_id": 0, "host": nodes[0]}, {"_id": 1, "host": nodes[1], "priority": 0}]
});

let primary = rst.getPrimary();
let secondary = rst.getSecondary();

/**
 * Part 1: Issue a fast op and make sure that we do *not* log it.
 * We ensure the op is always considered fast by vastly increasing the "slowMS" threshold.
 */

// Create collection explicitly so the insert doesn't have to do it.
assert.commandWorked(primary.getDB(name).createCollection("fastOp"));
rst.awaitReplication();

// Set "slowMS" to a very high value (in milliseconds).
assert.commandWorked(secondary.getDB(name).setProfilingLevel(1, 60 * 60 * 1000));

// Issue a write and make sure we replicate it.
assert.commandWorked(primary.getDB(name)["fastOp"].insert({"fast": "cheetah"}));
rst.awaitReplication();

// The op should not have been logged.
assert.throws(function() {
    checkLog.contains(secondary, "applied op: CRUD", 1 * 1000);
});

/**
 * Part 2: Issue a slow op and make sure that we *do* log it.
 * We use a failpoint in SyncTail::syncApply which blocks after we read the time at the start
 * of the application of the op, and we wait there to simulate slowness.
 */

// Create collection explicitly so the insert doesn't have to do it.
assert.commandWorked(primary.getDB(name).createCollection("slowOp"));
rst.awaitReplication();

// Set "slowMS" to a low value (in milliseconds).
assert.commandWorked(secondary.getDB(name).setProfilingLevel(1, 20));

// Hang right after taking note of the start time of the application.
assert.commandWorked(secondary.adminCommand(
    {configureFailPoint: "hangAfterRecordingOpApplicationStartTime", mode: "alwaysOn"}));

// Issue a write and make sure we've hit the failpoint before moving on.
assert.commandWorked(primary.getDB(name)["slowOp"].insert({"slow": "sloth"}));
checkLog.contains(secondary,
                  "syncApply - fail point hangAfterRecordingOpApplicationStartTime enabled");

// Wait for an amount of time safely above the "slowMS" we set.
sleep(0.5 * 1000);

// Disable the failpoint so the op finish can applying.
assert.commandWorked(secondary.adminCommand(
    {configureFailPoint: "hangAfterRecordingOpApplicationStartTime", mode: "off"}));

// Make sure we log that insert op.
rst.awaitReplication();
checkLog.contains(secondary, "applied op: CRUD");

rst.stopSet();
})();