summaryrefslogtreecommitdiff
path: root/jstests/replsets/sessions_collection_reaping.js
blob: bd7d5c4c5547e8e8555f391f826a3abe6de9ad27 (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
/**
 * Test that only the primary can reap a session and remove the config.transactions doc for the
 * session, and that arbiters never try to a reap session.
 */

(function() {
"use strict";

// This test makes assertions about the number of sessions, which are not compatible with
// implicit sessions.
TestData.disableImplicitSessions = true;

let replTest = new ReplSetTest({
    name: 'reaping',
    nodes: [
        {/* primary */},
        {/* secondary */ rsConfig: {priority: 0}},
        {/* arbiter */ rsConfig: {arbiterOnly: true}}
    ],
    nodeOptions: {
        setParameter: {
            TransactionRecordMinimumLifetimeMinutes: 0,
            storeFindAndModifyImagesInSideCollection: true
        }
    }
});
let nodes = replTest.startSet();

replTest.initiate();
let primary = replTest.getPrimary();
let sessionsCollOnPrimary = primary.getDB("config").system.sessions;
let transactionsCollOnPrimary = primary.getDB("config").transactions;
let imageCollOnPrimary = primary.getDB("config").image_collection;

replTest.awaitSecondaryNodes();
let secondary = replTest.getSecondary();
let arbiter = replTest.getArbiter();

const dbName = jsTestName();
const collName = "test";
const reapErrorMsgRegex =
    new RegExp("Sessions collection is not set up.*waiting until next sessions reap interval");

// Set up a session with a retryable insert and findAndModify.
let session = primary.startSession({retryWrites: 1});
assert.commandWorked(session.getDatabase(dbName)[collName].save({x: 1}));
let result =
    session.getDatabase(dbName)[collName].findAndModify({query: {x: 1}, update: {$set: {y: 1}}});
// The findAndModify helper returns the document and not the whole response. Assert on the value of
// `x`. Though it's expected a command error would become an exception that fails the test.
assert.eq(1, result['x'], "Whole result: " + result);
assert.commandWorked(primary.adminCommand({refreshLogicalSessionCacheNow: 1}));
assert.eq(1, sessionsCollOnPrimary.find().itcount());
assert.eq(1, transactionsCollOnPrimary.find().itcount());
assert.eq(1, imageCollOnPrimary.find().itcount());

// Remove the session doc so the session gets reaped when reapLogicalSessionCacheNow is run.
assert.commandWorked(sessionsCollOnPrimary.remove({}));

// Test that a reap on a secondary does not lead to the on-disk state reaping of the session
// since the session does not exist in the secondary's session catalog.
{
    assert.commandWorked(secondary.adminCommand({clearLog: 'global'}));
    assert.commandWorked(secondary.adminCommand({reapLogicalSessionCacheNow: 1}));

    assert.eq(1, transactionsCollOnPrimary.find().itcount());
    assert.eq(false, checkLog.checkContainsOnce(secondary, reapErrorMsgRegex));
}

// Test that a reap on an arbiter does not lead to reaping of the session.
{
    assert.commandWorked(arbiter.adminCommand({clearLog: 'global'}));
    assert.commandWorked(arbiter.adminCommand({reapLogicalSessionCacheNow: 1}));

    assert.eq(1, transactionsCollOnPrimary.find().itcount());

    if (!jsTest.options().useRandomBinVersionsWithinReplicaSet) {
        // Verify that the arbiter did not try to reap the session.
        assert.eq(false, checkLog.checkContainsOnce(arbiter, reapErrorMsgRegex));
    }
}

// Test that a reap on the primary works as expected.
{
    assert.commandWorked(primary.adminCommand({clearLog: 'global'}));
    assert.commandWorked(primary.adminCommand({reapLogicalSessionCacheNow: 1}));

    assert.eq(0, transactionsCollOnPrimary.find().itcount());
    assert.eq(0, imageCollOnPrimary.find().itcount());
}

replTest.stopSet();
})();