summaryrefslogtreecommitdiff
path: root/jstests/replsets/prepared_transaction_commands_fail_on_secondaries.js
blob: a1e4561edd78a6bb6ccd8560a26a9ca3f5aaf633 (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
/**
 * Tests that the 'prepareTransaction', 'commitTransaction', and 'abortTransaction' fail on
 * secondaries.
 *
 * @tags: [uses_transactions, uses_prepare_transaction]
 */

(function() {
"use strict";
load("jstests/core/txns/libs/prepare_helpers.js");

const name = "prepared_transaction_commands_fail_on_secondaries";
const rst = new ReplSetTest({
    nodes: [
        {},
        {rsConfig: {priority: 0}},
    ],
});
const nodes = rst.startSet();
rst.initiate();

const dbName = "test";
const collName = name;

const primary = rst.getPrimary();
const secondary = rst.getSecondary();
const testDB = primary.getDB(dbName);

assert.commandWorked(testDB.runCommand({create: collName, writeConcern: {w: "majority"}}));

const priSession = primary.startSession({causalConsistency: false});
const priSessionDB = priSession.getDatabase(dbName);
const priSessionColl = priSessionDB.getCollection(collName);

const secSession = PrepareHelpers.createSessionWithGivenId(
    secondary, priSession.getSessionId(), {causalConsistency: false});

priSession.startTransaction();
const doc = {
    _id: 1
};
assert.commandWorked(priSessionColl.insert(doc));
rst.awaitReplication();

jsTestLog("Test that prepare fails on a secondary");
const txnNumber = NumberLong(priSession.getTxnNumber_forTesting());
assert.commandFailedWithCode(secSession.getDatabase('admin').adminCommand(
                                 {prepareTransaction: 1, txnNumber: txnNumber, autocommit: false}),
                             ErrorCodes.NotWritablePrimary);

const prepareTimestamp = PrepareHelpers.prepareTransaction(priSession);
rst.awaitReplication();

jsTestLog("Test that prepared commit fails on a secondary");
// Add 1 to the increment so that the commitTimestamp is "after" the prepareTimestamp.
const commitTimestamp = Timestamp(prepareTimestamp.getTime(), prepareTimestamp.getInc() + 1);
assert.commandFailedWithCode(secSession.getDatabase('admin').adminCommand({
    commitTransaction: 1,
    commitTimestamp: commitTimestamp,
    txnNumber: txnNumber,
    autocommit: false
}),
                             ErrorCodes.NotWritablePrimary);

jsTestLog("Test that prepared abort fails on a secondary");
assert.commandFailedWithCode(secSession.getDatabase('admin').adminCommand(
                                 {abortTransaction: 1, txnNumber: txnNumber, autocommit: false}),
                             ErrorCodes.NotWritablePrimary);

jsTestLog("Test that we can still commit the transaction");
assert.commandWorked(PrepareHelpers.commitTransaction(priSession, commitTimestamp));
rst.awaitReplication();
assert.docEq(doc, testDB[collName].findOne());
assert.eq(1, testDB[collName].find().itcount());
assert.docEq(doc, secondary.getDB(dbName)[collName].findOne());
assert.eq(1, secondary.getDB(dbName)[collName].find().itcount());

rst.stopSet();
})();