summaryrefslogtreecommitdiff
path: root/jstests/replsets/retryable_write_concern.js
blob: 80ee2e7884c9552fead12d208738cc74ac6b67f5 (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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
/**
 * Tests for making sure that retried writes will wait properly for writeConcern.
 *
 * @tags: [uses_transactions, uses_prepare_transaction]
 */
(function() {

"use strict";

load("jstests/libs/retryable_writes_util.js");
load("jstests/libs/write_concern_util.js");

if (!RetryableWritesUtil.storageEngineSupportsRetryableWrites(jsTest.options().storageEngine)) {
    jsTestLog("Retryable writes are not supported, skipping test");
    return;
}

const kNodes = 2;

let replTest = new ReplSetTest({nodes: kNodes});
replTest.startSet({verbose: 1});
replTest.initiate();

let priConn = replTest.getPrimary();
let secConn = replTest.getSecondary();

// Stopping replication on secondaries can take up to 5 seconds normally. Set a small oplog
// getMore timeout so the test runs faster.
assert.commandWorked(
    secConn.adminCommand({configureFailPoint: 'setSmallOplogGetMoreMaxTimeMS', mode: 'alwaysOn'}));

let lsid = UUID();

// Start at an arbitrary txnNumber.
let txnNumber = 31;

txnNumber++;
runWriteConcernRetryabilityTest(priConn,
                                secConn,
                                {
                                    insert: 'user',
                                    documents: [{_id: 10}, {_id: 30}],
                                    ordered: false,
                                    lsid: {id: lsid},
                                    txnNumber: NumberLong(txnNumber),
                                    writeConcern: {w: 'majority', wtimeout: 200},
                                },
                                kNodes);

txnNumber++;
runWriteConcernRetryabilityTest(priConn,
                                secConn,
                                {
                                    update: 'user',
                                    updates: [
                                        {q: {_id: 10}, u: {$inc: {x: 1}}},
                                    ],
                                    ordered: false,
                                    lsid: {id: lsid},
                                    txnNumber: NumberLong(txnNumber),
                                    writeConcern: {w: 'majority', wtimeout: 200},
                                },
                                kNodes);

txnNumber++;
runWriteConcernRetryabilityTest(priConn,
                                secConn,
                                {
                                    delete: 'user',
                                    deletes: [{q: {x: 1}, limit: 1}, {q: {y: 1}, limit: 1}],
                                    ordered: false,
                                    lsid: {id: lsid},
                                    txnNumber: NumberLong(txnNumber),
                                    writeConcern: {w: 'majority', wtimeout: 200},
                                },
                                kNodes);

txnNumber++;
runWriteConcernRetryabilityTest(priConn,
                                secConn,
                                {
                                    findAndModify: 'user',
                                    query: {_id: 60},
                                    update: {$inc: {x: 1}},
                                    new: true,
                                    upsert: true,
                                    lsid: {id: lsid},
                                    txnNumber: NumberLong(txnNumber),
                                    writeConcern: {w: 'majority', wtimeout: 200},
                                },
                                kNodes);

txnNumber++;
runWriteConcernRetryabilityTest(priConn,
                                secConn,
                                {
                                    commitTransaction: 1,
                                    lsid: {id: lsid},
                                    txnNumber: NumberLong(txnNumber),
                                    autocommit: false,
                                    writeConcern: {w: 'majority', wtimeout: 200},
                                },
                                kNodes,
                                'admin',
                                function(conn) {
                                    assert.commandWorked(conn.getDB('test').runCommand({
                                        insert: 'user',
                                        documents: [{_id: 80}, {_id: 90}],
                                        ordered: false,
                                        lsid: {id: lsid},
                                        txnNumber: NumberLong(txnNumber),
                                        readConcern: {level: 'snapshot'},
                                        autocommit: false,
                                        startTransaction: true
                                    }));
                                });

txnNumber++;
runWriteConcernRetryabilityTest(priConn,
                                secConn,
                                {
                                    prepareTransaction: 1,
                                    lsid: {id: lsid},
                                    txnNumber: NumberLong(txnNumber),
                                    autocommit: false,
                                    writeConcern: {w: 'majority', wtimeout: 200},
                                },
                                kNodes,
                                'admin',
                                function(conn) {
                                    assert.commandWorked(conn.getDB('test').runCommand({
                                        insert: 'user',
                                        documents: [{_id: 100}, {_id: 110}],
                                        ordered: false,
                                        lsid: {id: lsid},
                                        txnNumber: NumberLong(txnNumber),
                                        readConcern: {level: 'snapshot'},
                                        autocommit: false,
                                        startTransaction: true
                                    }));
                                });
assert.commandWorked(priConn.adminCommand({
    abortTransaction: 1,
    lsid: {id: lsid},
    txnNumber: NumberLong(txnNumber),
    autocommit: false,
    writeConcern: {w: 'majority'},
}));

txnNumber++;
runWriteConcernRetryabilityTest(priConn,
                                secConn,
                                {
                                    abortTransaction: 1,
                                    lsid: {id: lsid},
                                    txnNumber: NumberLong(txnNumber),
                                    autocommit: false,
                                    writeConcern: {w: 'majority', wtimeout: 200},
                                },
                                kNodes,
                                'admin',
                                function(conn) {
                                    assert.commandWorked(conn.getDB('test').runCommand({
                                        insert: 'user',
                                        documents: [{_id: 120}, {_id: 130}],
                                        ordered: false,
                                        lsid: {id: lsid},
                                        txnNumber: NumberLong(txnNumber),
                                        readConcern: {level: 'snapshot'},
                                        autocommit: false,
                                        startTransaction: true
                                    }));
                                    assert.commandWorked(conn.adminCommand({
                                        prepareTransaction: 1,
                                        lsid: {id: lsid},
                                        txnNumber: NumberLong(txnNumber),
                                        autocommit: false,
                                        writeConcern: {w: 'majority'},
                                    }));
                                });

txnNumber++;
assert.commandWorked(priConn.getDB('test').runCommand({
    insert: 'user',
    documents: [{_id: 140}, {_id: 150}],
    ordered: false,
    lsid: {id: lsid},
    txnNumber: NumberLong(txnNumber),
    readConcern: {level: 'snapshot'},
    autocommit: false,
    startTransaction: true
}));
const prepareTS = assert
                      .commandWorked(priConn.adminCommand({
                          prepareTransaction: 1,
                          lsid: {id: lsid},
                          txnNumber: NumberLong(txnNumber),
                          autocommit: false,
                          writeConcern: {w: 'majority'},
                      }))
                      .prepareTimestamp;
runWriteConcernRetryabilityTest(priConn,
                                secConn,
                                {
                                    commitTransaction: 1,
                                    commitTimestamp: prepareTS,
                                    lsid: {id: lsid},
                                    txnNumber: NumberLong(txnNumber),
                                    autocommit: false,
                                    writeConcern: {w: 'majority', wtimeout: 200},
                                },
                                kNodes,
                                'admin');

replTest.stopSet();
})();