summaryrefslogtreecommitdiff
path: root/jstests/noPassthrough/transaction_reaper.js
diff options
context:
space:
mode:
Diffstat (limited to 'jstests/noPassthrough/transaction_reaper.js')
-rw-r--r--jstests/noPassthrough/transaction_reaper.js149
1 files changed, 149 insertions, 0 deletions
diff --git a/jstests/noPassthrough/transaction_reaper.js b/jstests/noPassthrough/transaction_reaper.js
new file mode 100644
index 00000000000..c9a9e992cb2
--- /dev/null
+++ b/jstests/noPassthrough/transaction_reaper.js
@@ -0,0 +1,149 @@
+(function() {
+ 'use strict';
+
+ function Repl(lifetime) {
+ this.rst = new ReplSetTest({
+ nodes: 1,
+ nodeOptions: {setParameter: {TransactionRecordMinimumLifetimeMinutes: lifetime}},
+ });
+ this.rst.startSet();
+ this.rst.initiate();
+ }
+
+ Repl.prototype.stop = function() {
+ this.rst.stopSet();
+ };
+
+ Repl.prototype.getConn = function() {
+ return this.rst.getPrimary();
+ };
+
+ Repl.prototype.getTransactionConn = function() {
+ return this.rst.getPrimary();
+ };
+
+ function Sharding(lifetime) {
+ this.st = new ShardingTest({
+ shards: 1,
+ mongos: 1,
+ config: 1,
+ other: {
+ rs: true,
+ rsOptions: {setParameter: {TransactionRecordMinimumLifetimeMinutes: lifetime}},
+ rs0: {nodes: 1},
+ },
+ });
+
+ this.st.s0.getDB("admin").runCommand({enableSharding: "test"});
+ this.st.s0.getDB("admin").runCommand({shardCollection: "test.test", key: {_id: 1}});
+ }
+
+ Sharding.prototype.stop = function() {
+ this.st.stop();
+ };
+
+ Sharding.prototype.getConn = function() {
+ return this.st.s0;
+ };
+
+ Sharding.prototype.getTransactionConn = function() {
+ return this.st.rs0.getPrimary();
+ };
+
+ const nSessions = 1500;
+
+ function Fixture(impl) {
+ this.impl = impl;
+ this.conn = impl.getConn();
+ this.transactionConn = impl.getTransactionConn();
+
+ this.sessions = [];
+
+ for (var i = 0; i < nSessions; i++) {
+ // make a session and get it to the collection
+ var session = this.conn.startSession({retryWrites: 1});
+ session.getDatabase("test").test.count({});
+ this.sessions.push(session);
+ }
+
+ this.refresh();
+ this.assertOutstandingTransactions(0);
+ this.assertOutstandingSessions(nSessions);
+
+ for (var i = 0; i < nSessions; i++) {
+ // make a session and get it to the collection
+ var session = this.sessions[i];
+ session.getDatabase("test").test.save({a: 1});
+ }
+
+ // Ensure a write flushes a transaction
+ this.assertOutstandingTransactions(nSessions);
+ this.assertOutstandingSessions(nSessions);
+
+ // Ensure a refresh/reap doesn't remove the transaction
+ this.refresh();
+ this.reap();
+ this.assertOutstandingTransactions(nSessions);
+ this.assertOutstandingSessions(nSessions);
+ }
+
+ Fixture.prototype.assertOutstandingTransactions = function(count) {
+ assert.eq(count, this.transactionConn.getDB("config").transactions.count());
+ };
+
+ Fixture.prototype.assertOutstandingSessions = function(count) {
+ assert.eq(count, this.getDB("admin").system.sessions.count());
+ };
+
+ Fixture.prototype.refresh = function() {
+ assert.commandWorked(this.getDB("admin").runCommand({refreshLogicalSessionCacheNow: 1}));
+ };
+
+ Fixture.prototype.reap = function() {
+ assert.commandWorked(
+ this.transactionConn.getDB("admin").runCommand({reapLogicalSessionCacheNow: 1}));
+ };
+
+ Fixture.prototype.getDB = function(db) {
+ return this.conn.getDB(db);
+ };
+
+ Fixture.prototype.stop = function() {
+ this.sessions.forEach(function(session) {
+ session.endSession();
+ });
+ return this.impl.stop();
+ };
+
+ [Repl, Sharding].forEach(function(Impl) {
+ {
+ var fixture = new Fixture(new Impl(-1));
+ // Remove a session
+ fixture.getDB("admin").system.sessions.remove({});
+ fixture.assertOutstandingTransactions(nSessions);
+ fixture.assertOutstandingSessions(0);
+
+ // See the transaction get reaped as a result
+ fixture.reap();
+ fixture.assertOutstandingTransactions(0);
+ fixture.assertOutstandingSessions(0);
+
+ fixture.stop();
+ }
+
+ {
+ var fixture = new Fixture(new Impl(30));
+ // Remove a session
+ fixture.getDB("admin").system.sessions.remove({});
+ fixture.assertOutstandingTransactions(nSessions);
+ fixture.assertOutstandingSessions(0);
+
+ // See the transaction was not reaped as a result
+ fixture.reap();
+ fixture.assertOutstandingTransactions(nSessions);
+ fixture.assertOutstandingSessions(0);
+
+ fixture.stop();
+ }
+ });
+})();