2018-07-10 23:19:13 +02:00
|
|
|
// Test parsing of readConcern level 'snapshot' on mongos.
|
2019-02-13 19:45:32 +01:00
|
|
|
// @tags: [requires_replication,requires_sharding, uses_transactions, uses_atclustertime]
|
2018-03-08 21:17:56 +01:00
|
|
|
(function() {
|
2019-07-27 00:20:35 +02:00
|
|
|
"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());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Runs the command as the first in a multi statement txn that is aborted right after, expecting
|
|
|
|
// failure with the given error code.
|
|
|
|
function expectFailInTxnThenAbort(session, sessionConn, expectedErrorCode, cmdObj) {
|
|
|
|
session.startTransaction();
|
|
|
|
assert.commandFailedWithCode(sessionConn.runCommand(cmdObj), expectedErrorCode);
|
|
|
|
assert.commandFailedWithCode(session.abortTransaction_forTesting(),
|
|
|
|
ErrorCodes.NoSuchTransaction);
|
|
|
|
}
|
|
|
|
|
|
|
|
const dbName = "test";
|
|
|
|
const collName = "coll";
|
|
|
|
|
|
|
|
let st = new ShardingTest({shards: 1, rs: {nodes: 2}, config: 2, mongos: 1});
|
|
|
|
let testDB = st.getDB(dbName);
|
|
|
|
let coll = testDB.coll;
|
|
|
|
|
|
|
|
// Insert data to create the collection.
|
|
|
|
assert.writeOK(testDB[collName].insert({x: 1}));
|
|
|
|
|
|
|
|
flushRoutersAndRefreshShardMetadata(st, {ns: dbName + "." + collName, dbNames: [dbName]});
|
|
|
|
|
|
|
|
// noPassthrough tests
|
|
|
|
|
|
|
|
// readConcern 'snapshot' is not allowed outside session context.
|
|
|
|
assert.commandFailedWithCode(testDB.runCommand({find: collName, readConcern: {level: "snapshot"}}),
|
|
|
|
ErrorCodes.InvalidOptions);
|
|
|
|
|
|
|
|
let session = testDB.getMongo().startSession({causalConsistency: false});
|
|
|
|
let sessionDb = session.getDatabase(dbName);
|
|
|
|
|
|
|
|
// readConcern 'snapshot' is not allowed outside transaction context.
|
|
|
|
assert.commandFailedWithCode(sessionDb.runCommand({
|
|
|
|
find: collName,
|
|
|
|
readConcern: {level: "snapshot"},
|
|
|
|
}),
|
|
|
|
ErrorCodes.InvalidOptions);
|
|
|
|
|
|
|
|
// readConcern 'snapshot' is not allowed with 'atClusterTime'.
|
|
|
|
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;
|
|
|
|
|
|
|
|
expectFailInTxnThenAbort(session, sessionDb, ErrorCodes.InvalidOptions, {
|
|
|
|
find: collName,
|
|
|
|
readConcern: {level: "snapshot", atClusterTime: clusterTime},
|
|
|
|
});
|
|
|
|
|
|
|
|
// Passthrough tests. There are parts not implemented on mongod and mongos, they are tracked by
|
|
|
|
// separate jiras
|
|
|
|
|
|
|
|
// 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"},
|
|
|
|
});
|
|
|
|
|
|
|
|
expectSuccessInTxnThenAbort(session, sessionDb, {
|
|
|
|
aggregate: collName,
|
|
|
|
pipeline: [],
|
|
|
|
cursor: {},
|
|
|
|
readConcern: {level: "snapshot"},
|
|
|
|
});
|
|
|
|
|
|
|
|
// readConcern 'snapshot' is supported by find on mongos.
|
|
|
|
expectSuccessInTxnThenAbort(session, sessionDb, {
|
|
|
|
find: collName,
|
|
|
|
readConcern: {level: "snapshot"},
|
|
|
|
});
|
|
|
|
|
|
|
|
// readConcern 'snapshot' is supported by distinct on mongos.
|
|
|
|
expectSuccessInTxnThenAbort(session, sessionDb, {
|
|
|
|
distinct: collName,
|
|
|
|
key: "x",
|
|
|
|
readConcern: {level: "snapshot"},
|
|
|
|
});
|
|
|
|
|
|
|
|
// 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},
|
|
|
|
});
|
|
|
|
|
|
|
|
st.stop();
|
2018-03-08 21:17:56 +01:00
|
|
|
}());
|