summaryrefslogtreecommitdiff
path: root/jstests/replsets/prepared_transaction_on_failover.js
diff options
context:
space:
mode:
Diffstat (limited to 'jstests/replsets/prepared_transaction_on_failover.js')
-rw-r--r--jstests/replsets/prepared_transaction_on_failover.js251
1 files changed, 124 insertions, 127 deletions
diff --git a/jstests/replsets/prepared_transaction_on_failover.js b/jstests/replsets/prepared_transaction_on_failover.js
index e5d6bf84a1e..43689b95c1e 100644
--- a/jstests/replsets/prepared_transaction_on_failover.js
+++ b/jstests/replsets/prepared_transaction_on_failover.js
@@ -4,131 +4,128 @@
* @tags: [uses_transactions, uses_prepare_transaction]
*/
(function() {
- "use strict";
- load("jstests/core/txns/libs/prepare_helpers.js");
- load("jstests/replsets/rslib.js"); // For reconnect()
-
- const replTest = new ReplSetTest({nodes: 2});
- replTest.startSet();
- replTest.initiate();
-
- const dbName = jsTest.name();
- const collName = "coll";
- const otherDbName = dbName + "_other";
-
- function testTransactionsWithFailover(doWork, stepDown, postCommit) {
- const primary = replTest.getPrimary();
- const newPrimary = replTest.getSecondary();
- const testDB = primary.getDB(dbName);
-
- testDB.dropDatabase();
- testDB.getSiblingDB(otherDbName).dropDatabase();
- assert.commandWorked(testDB.runCommand({create: collName, writeConcern: {w: "majority"}}));
-
- jsTestLog("Starting transaction");
- const session = primary.startSession({causalConsistency: false});
- session.startTransaction({writeConcern: {w: "majority"}});
-
- doWork(primary, session);
-
- jsTestLog("Putting transaction into prepare");
- const prepareTimestamp = PrepareHelpers.prepareTransaction(session);
- replTest.awaitReplication();
-
- stepDown();
- reconnect(primary);
-
- jsTestLog("Waiting for the other node to run for election and become primary");
- assert.eq(replTest.getPrimary(), newPrimary);
-
- jsTestLog("Creating an unrelated collection");
- // Application of an unrelated DDL command needs a strong lock on secondary. Make sure
- // the prepared transactions have yielded their locks on secondary.
- assert.commandWorked(newPrimary.getDB(otherDbName).runCommand({create: collName}));
- replTest.awaitReplication();
-
- jsTestLog("Dropping the collection in use cannot acquire the lock");
- assert.commandFailedWithCode(
- newPrimary.getDB(testDB).runCommand({drop: collName, maxTimeMS: 1000}),
- ErrorCodes.MaxTimeMSExpired);
-
- jsTestLog("Committing transaction on the new primary");
- // Create a proxy session to reuse the session state of the old primary.
- const newSession = new _DelegatingDriverSession(newPrimary, session);
-
- assert.commandWorked(PrepareHelpers.commitTransaction(newSession, prepareTimestamp));
- replTest.awaitReplication();
-
- postCommit(primary, newPrimary);
-
- jsTestLog("Running another transaction on the new primary");
- const secondSession = newPrimary.startSession({causalConsistency: false});
- secondSession.startTransaction({writeConcern: {w: "majority"}});
- assert.commandWorked(
- secondSession.getDatabase(dbName).getCollection(collName).insert({_id: "second-doc"}));
- assert.commandWorked(secondSession.commitTransaction_forTesting());
-
- // Unfreeze the original primary so that it can stand for election again for the next test.
- assert.commandWorked(primary.adminCommand({replSetFreeze: 0}));
- }
-
- function doInsert(primary, session) {
- const doc = {_id: "txn on primary " + primary};
- jsTestLog("Inserting a document in a transaction.");
- assert.commandWorked(session.getDatabase(dbName).getCollection(collName).insert(doc));
- }
- function postInsert(primary, newPrimary) {
- const doc = {_id: "txn on primary " + primary};
- assert.docEq(doc, primary.getDB(dbName).getCollection(collName).findOne());
- assert.docEq(doc, newPrimary.getDB(dbName).getCollection(collName).findOne());
- }
-
- function doInsertTextSearch(primary, session) {
- // Create an index outside of the transaction.
- assert.commandWorked(
- primary.getDB(dbName).getCollection(collName).createIndex({text: "text"}));
-
- // Do the followings in a transaction.
- jsTestLog("Inserting a document in a transaction.");
- assert.commandWorked(
- session.getDatabase(dbName).getCollection(collName).insert({text: "text"}));
- // Text search will recursively acquire the global lock. This tests that yielding
- // recursively held locks works on step down.
- jsTestLog("Doing a text search in a transaction.");
- assert.eq(1,
- session.getDatabase(dbName)
- .getCollection(collName)
- .find({$text: {$search: "text"}})
- .itcount());
- }
- function postInsertTextSearch(primary, newPrimary) {
- assert.eq(1,
- primary.getDB(dbName)
- .getCollection(collName)
- .find({$text: {$search: "text"}})
- .itcount());
- assert.eq(1,
- newPrimary.getDB(dbName)
- .getCollection(collName)
- .find({$text: {$search: "text"}})
- .itcount());
- }
-
- function stepDownViaHeartbeat() {
- jsTestLog("Stepping down primary via heartbeat");
- replTest.stepUp(replTest.getSecondary());
- }
-
- function stepDownViaCommand() {
- jsTestLog("Stepping down primary via command");
- assert.commandWorked(replTest.getPrimary().adminCommand({replSetStepDown: 10}));
- }
-
- testTransactionsWithFailover(doInsert, stepDownViaHeartbeat, postInsert);
- testTransactionsWithFailover(doInsert, stepDownViaCommand, postInsert);
-
- testTransactionsWithFailover(doInsertTextSearch, stepDownViaHeartbeat, postInsertTextSearch);
- testTransactionsWithFailover(doInsertTextSearch, stepDownViaCommand, postInsertTextSearch);
-
- replTest.stopSet();
+"use strict";
+load("jstests/core/txns/libs/prepare_helpers.js");
+load("jstests/replsets/rslib.js"); // For reconnect()
+
+const replTest = new ReplSetTest({nodes: 2});
+replTest.startSet();
+replTest.initiate();
+
+const dbName = jsTest.name();
+const collName = "coll";
+const otherDbName = dbName + "_other";
+
+function testTransactionsWithFailover(doWork, stepDown, postCommit) {
+ const primary = replTest.getPrimary();
+ const newPrimary = replTest.getSecondary();
+ const testDB = primary.getDB(dbName);
+
+ testDB.dropDatabase();
+ testDB.getSiblingDB(otherDbName).dropDatabase();
+ assert.commandWorked(testDB.runCommand({create: collName, writeConcern: {w: "majority"}}));
+
+ jsTestLog("Starting transaction");
+ const session = primary.startSession({causalConsistency: false});
+ session.startTransaction({writeConcern: {w: "majority"}});
+
+ doWork(primary, session);
+
+ jsTestLog("Putting transaction into prepare");
+ const prepareTimestamp = PrepareHelpers.prepareTransaction(session);
+ replTest.awaitReplication();
+
+ stepDown();
+ reconnect(primary);
+
+ jsTestLog("Waiting for the other node to run for election and become primary");
+ assert.eq(replTest.getPrimary(), newPrimary);
+
+ jsTestLog("Creating an unrelated collection");
+ // Application of an unrelated DDL command needs a strong lock on secondary. Make sure
+ // the prepared transactions have yielded their locks on secondary.
+ assert.commandWorked(newPrimary.getDB(otherDbName).runCommand({create: collName}));
+ replTest.awaitReplication();
+
+ jsTestLog("Dropping the collection in use cannot acquire the lock");
+ assert.commandFailedWithCode(
+ newPrimary.getDB(testDB).runCommand({drop: collName, maxTimeMS: 1000}),
+ ErrorCodes.MaxTimeMSExpired);
+
+ jsTestLog("Committing transaction on the new primary");
+ // Create a proxy session to reuse the session state of the old primary.
+ const newSession = new _DelegatingDriverSession(newPrimary, session);
+
+ assert.commandWorked(PrepareHelpers.commitTransaction(newSession, prepareTimestamp));
+ replTest.awaitReplication();
+
+ postCommit(primary, newPrimary);
+
+ jsTestLog("Running another transaction on the new primary");
+ const secondSession = newPrimary.startSession({causalConsistency: false});
+ secondSession.startTransaction({writeConcern: {w: "majority"}});
+ assert.commandWorked(
+ secondSession.getDatabase(dbName).getCollection(collName).insert({_id: "second-doc"}));
+ assert.commandWorked(secondSession.commitTransaction_forTesting());
+
+ // Unfreeze the original primary so that it can stand for election again for the next test.
+ assert.commandWorked(primary.adminCommand({replSetFreeze: 0}));
+}
+
+function doInsert(primary, session) {
+ const doc = {_id: "txn on primary " + primary};
+ jsTestLog("Inserting a document in a transaction.");
+ assert.commandWorked(session.getDatabase(dbName).getCollection(collName).insert(doc));
+}
+function postInsert(primary, newPrimary) {
+ const doc = {_id: "txn on primary " + primary};
+ assert.docEq(doc, primary.getDB(dbName).getCollection(collName).findOne());
+ assert.docEq(doc, newPrimary.getDB(dbName).getCollection(collName).findOne());
+}
+
+function doInsertTextSearch(primary, session) {
+ // Create an index outside of the transaction.
+ assert.commandWorked(primary.getDB(dbName).getCollection(collName).createIndex({text: "text"}));
+
+ // Do the followings in a transaction.
+ jsTestLog("Inserting a document in a transaction.");
+ assert.commandWorked(
+ session.getDatabase(dbName).getCollection(collName).insert({text: "text"}));
+ // Text search will recursively acquire the global lock. This tests that yielding
+ // recursively held locks works on step down.
+ jsTestLog("Doing a text search in a transaction.");
+ assert.eq(1,
+ session.getDatabase(dbName)
+ .getCollection(collName)
+ .find({$text: {$search: "text"}})
+ .itcount());
+}
+function postInsertTextSearch(primary, newPrimary) {
+ assert.eq(
+ 1,
+ primary.getDB(dbName).getCollection(collName).find({$text: {$search: "text"}}).itcount());
+ assert.eq(1,
+ newPrimary.getDB(dbName)
+ .getCollection(collName)
+ .find({$text: {$search: "text"}})
+ .itcount());
+}
+
+function stepDownViaHeartbeat() {
+ jsTestLog("Stepping down primary via heartbeat");
+ replTest.stepUp(replTest.getSecondary());
+}
+
+function stepDownViaCommand() {
+ jsTestLog("Stepping down primary via command");
+ assert.commandWorked(replTest.getPrimary().adminCommand({replSetStepDown: 10}));
+}
+
+testTransactionsWithFailover(doInsert, stepDownViaHeartbeat, postInsert);
+testTransactionsWithFailover(doInsert, stepDownViaCommand, postInsert);
+
+testTransactionsWithFailover(doInsertTextSearch, stepDownViaHeartbeat, postInsertTextSearch);
+testTransactionsWithFailover(doInsertTextSearch, stepDownViaCommand, postInsertTextSearch);
+
+replTest.stopSet();
})();