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
|
// Test parsing of readConcern level 'snapshot' on mongos.
// @tags: [requires_replication,requires_sharding, uses_transactions, uses_atclustertime]
(function() {
"use strict";
load("jstests/sharding/libs/sharded_transactions_helpers.js");
// Runs the command as the first in a multi statement txn that is aborted right after, expecting
// success.
function expectSuccessInTxnThenAbort(session, sessionConn, cmdObj) {
session.startTransaction();
assert.commandWorked(sessionConn.runCommand(cmdObj));
assert.commandWorked(session.abortTransaction_forTesting());
}
const dbName = "test";
const collName = "coll";
let st = new ShardingTest({shards: 1, rs: {nodes: 2}, config: 2, mongos: 1});
let testDB = st.getDB(dbName);
// Insert data to create the collection.
assert.commandWorked(testDB[collName].insert({x: 1}));
flushRoutersAndRefreshShardMetadata(st, {ns: dbName + "." + collName, dbNames: [dbName]});
// Test snapshot in a transaction.
let session = testDB.getMongo().startSession({causalConsistency: false});
let sessionDb = session.getDatabase(dbName);
// readConcern 'snapshot' is supported by insert on mongos in a transaction.
expectSuccessInTxnThenAbort(session, sessionDb, {
insert: collName,
documents: [{_id: "single-insert"}],
readConcern: {level: "snapshot"},
});
// readConcern 'snapshot' is supported by update on mongos in a transaction.
expectSuccessInTxnThenAbort(session, sessionDb, {
update: collName,
updates: [{q: {_id: 0}, u: {$inc: {a: 1}}}],
readConcern: {level: "snapshot"},
});
// readConcern 'snapshot' is supported by delete on mongos in a transaction.
expectSuccessInTxnThenAbort(session, sessionDb, {
delete: collName,
deletes: [{q: {}, limit: 1}],
readConcern: {level: "snapshot"},
});
// readConcern 'snapshot' is supported by findAndModify on mongos in a transaction.
expectSuccessInTxnThenAbort(session, sessionDb, {
findAndModify: collName,
query: {},
update: {$set: {a: 1}},
readConcern: {level: "snapshot"},
});
// readConcern 'snapshot' is supported by aggregate on mongos in a transaction.
expectSuccessInTxnThenAbort(session, sessionDb, {
aggregate: collName,
pipeline: [],
cursor: {},
readConcern: {level: "snapshot"},
});
// readConcern 'snapshot' is supported by find on mongos in a transaction.
expectSuccessInTxnThenAbort(session, sessionDb, {
find: collName,
readConcern: {level: "snapshot"},
});
// readConcern 'snapshot' is supported by distinct on mongos in a transaction.
expectSuccessInTxnThenAbort(session, sessionDb, {
distinct: collName,
key: "x",
readConcern: {level: "snapshot"},
});
let pingRes = assert.commandWorked(st.s0.adminCommand({ping: 1}));
assert(pingRes.hasOwnProperty("$clusterTime"), tojson(pingRes));
assert(pingRes.$clusterTime.hasOwnProperty("clusterTime"), tojson(pingRes));
const clusterTime = pingRes.$clusterTime.clusterTime;
// readConcern 'snapshot' is allowed with 'afterClusterTime'.
expectSuccessInTxnThenAbort(session, sessionDb, {
find: collName,
readConcern: {level: "snapshot", afterClusterTime: clusterTime},
});
expectSuccessInTxnThenAbort(session, sessionDb, {
aggregate: collName,
pipeline: [],
cursor: {},
readConcern: {level: "snapshot", afterClusterTime: clusterTime},
});
// Test snapshot outside of transactions on mongos.
const snapshotReadConcern = {
level: "snapshot"
};
// readConcern 'snapshot' is supported by find outside of transactions on mongos.
assert.commandWorked(testDB.runCommand({find: collName, readConcern: snapshotReadConcern}));
// readConcern 'snapshot' is supported by aggregate outside of transactions on mongos.
assert.commandWorked(testDB.runCommand(
{aggregate: collName, pipeline: [], cursor: {}, readConcern: snapshotReadConcern}));
// readConcern 'snapshot' is supported by distinct outside of transactions on mongos.
assert.commandWorked(
testDB.runCommand({distinct: collName, key: "x", readConcern: snapshotReadConcern}));
// readConcern 'snapshot' is not supported by count on mongos.
assert.commandFailedWithCode(testDB.runCommand({count: collName, readConcern: snapshotReadConcern}),
ErrorCodes.InvalidOptions);
// readConcern 'snapshot' is not supported by findAndModify outside of transactions on mongos.
assert.commandFailedWithCode(testDB.runCommand({
findAndModify: collName,
query: {},
update: {$set: {a: 1}},
readConcern: snapshotReadConcern,
}),
ErrorCodes.InvalidOptions);
st.stop();
}());
|