mirror of https://github.com/mongodb/mongo
80 lines
2.8 KiB
JavaScript
80 lines
2.8 KiB
JavaScript
// Tests that a transaction expires and is then aborted by the server. Uses the server parameter
|
|
// 'transactionLifetimeLimitSeconds' to lower the transaction lifetime for quicker transaction
|
|
// expiration. This is the mongos version for: jstests/core/txns/abort_expired_transaction.js.
|
|
//
|
|
// @tags: [uses_transactions, uses_multi_shard_transaction]
|
|
|
|
import {withRetryOnTransientTxnError} from "jstests/libs/auto_retry_transaction_in_sharding.js";
|
|
import {ShardingTest} from "jstests/libs/shardingtest.js";
|
|
|
|
let st = new ShardingTest({shards: 2});
|
|
|
|
assert.commandWorked(st.s.adminCommand({enableSharding: "test", primaryShard: st.shard0.name}));
|
|
assert.commandWorked(st.s.adminCommand({shardCollection: "test.user", key: {x: 1}}));
|
|
assert.commandWorked(st.s.adminCommand({split: "test.user", middle: {x: 0}}));
|
|
assert.commandWorked(st.s.adminCommand({moveChunk: "test.user", find: {x: 0}, to: st.shard1.name}));
|
|
|
|
let lowerTxnTimeout = (conn) => {
|
|
assert.commandWorked(conn.getDB("admin").runCommand({setParameter: 1, transactionLifetimeLimitSeconds: 1}));
|
|
};
|
|
|
|
st.rs0.nodes.forEach(lowerTxnTimeout);
|
|
st.rs1.nodes.forEach(lowerTxnTimeout);
|
|
|
|
let testDB = st.s.getDB("test");
|
|
|
|
// Create the collections in the shards outside the transactions.
|
|
assert.commandWorked(testDB.runCommand({insert: "user", documents: [{x: -1}, {x: 1}], writeConcern: {w: "majority"}}));
|
|
|
|
const session = st.s.startSession();
|
|
const sessionDb = session.getDatabase("test");
|
|
|
|
let txnNumber = 0;
|
|
|
|
withRetryOnTransientTxnError(() => {
|
|
txnNumber++;
|
|
assert.commandWorked(
|
|
sessionDb.runCommand({
|
|
insert: "user",
|
|
documents: [{x: -10}, {x: 10}],
|
|
txnNumber: NumberLong(txnNumber),
|
|
startTransaction: true,
|
|
autocommit: false,
|
|
}),
|
|
);
|
|
});
|
|
|
|
// We can deterministically wait for the transaction to be aborted by waiting for currentOp
|
|
// to cease reporting the inactive transaction: the transaction should disappear from the
|
|
// currentOp results once aborted.
|
|
assert.soon(function () {
|
|
const sessionFilter = {
|
|
active: false,
|
|
opid: {$exists: false},
|
|
desc: "inactive transaction",
|
|
"transaction.parameters.txnNumber": NumberLong(txnNumber),
|
|
"lsid.id": session.getSessionId().id,
|
|
};
|
|
|
|
const priConn = st.rs0.getPrimary();
|
|
const res = priConn
|
|
.getDB("admin")
|
|
.aggregate([{$currentOp: {allUsers: true, idleSessions: true}}, {$match: sessionFilter}]);
|
|
|
|
return res.itcount() == 0;
|
|
}, "currentOp reports that the idle transaction still exists, it has not been " + "aborted as expected.");
|
|
|
|
assert.commandFailedWithCode(
|
|
sessionDb.runCommand({
|
|
insert: "user",
|
|
documents: [{x: -100}, {x: 100}],
|
|
txnNumber: NumberLong(txnNumber),
|
|
autocommit: false,
|
|
}),
|
|
ErrorCodes.NoSuchTransaction,
|
|
);
|
|
|
|
session.endSession();
|
|
|
|
st.stop();
|