mirror of https://github.com/mongodb/mongo
87 lines
3.1 KiB
JavaScript
87 lines
3.1 KiB
JavaScript
/**
|
|
* Tests prepared transactions with an explicitly set apiVersion.
|
|
*/
|
|
// TODO (SERVER-111718): Remove this test if it will be covered elsewhere, or relocate it.
|
|
import {PrepareHelpers} from "jstests/core/txns/libs/prepare_helpers.js";
|
|
import {ReplSetTest} from "jstests/libs/replsettest.js";
|
|
|
|
// Override all commands to explicitly set 'apiVersion'.
|
|
import("jstests/libs/override_methods/set_api_version.js");
|
|
|
|
const dbName = "prepare_txn_with_api";
|
|
const collName = "test";
|
|
|
|
const rst = new ReplSetTest({nodes: 2});
|
|
rst.startSet();
|
|
rst.initiate();
|
|
|
|
let primary = rst.getPrimary();
|
|
let secondary = rst.getSecondary();
|
|
const testDB = primary.getDB(dbName);
|
|
const testColl = testDB.getCollection(collName);
|
|
|
|
let oldDoc = {_id: 42};
|
|
let inc = 1;
|
|
// First create the collection.
|
|
assert.commandWorked(testColl.insert(oldDoc));
|
|
|
|
const runTest = function (failover, commit) {
|
|
jsTestLog(`Testing ${commit ? "Commiting" : "Aborting"} with ${failover ? "Failover" : "Restarting Primary"}.`);
|
|
const newDoc = {_id: 42, x: inc++};
|
|
let session = primary.startSession();
|
|
const sessionColl = session.getDatabase(dbName).getCollection(collName);
|
|
|
|
session.startTransaction();
|
|
assert.commandWorked(sessionColl.update(oldDoc, newDoc));
|
|
|
|
// Prepare a transaction. This will be replicated to the secondary.
|
|
const prepareTimestamp = PrepareHelpers.prepareTransaction(session);
|
|
rst.awaitReplication();
|
|
|
|
// Stepping up Secondary.
|
|
rst.stepUp(secondary);
|
|
rst.awaitReplication();
|
|
rst.awaitSecondaryNodes(null, [primary]);
|
|
rst.waitForState(secondary, ReplSetTest.State.PRIMARY);
|
|
if (failover) {
|
|
session = new _DelegatingDriverSession(secondary, session);
|
|
} else {
|
|
// Restart the primary.
|
|
rst.restart(primary);
|
|
rst.stepUp(primary);
|
|
rst.waitForState(primary, ReplSetTest.State.PRIMARY);
|
|
rst.awaitSecondaryNodes(null, [secondary]);
|
|
}
|
|
|
|
const newPrimary = rst.getPrimary();
|
|
assert.eq(failover ? secondary : primary, newPrimary, "Wrong primary");
|
|
// The prepare entry must be majority committed on the new primary before we commit the
|
|
// prepared transaction, so we wait for the 'lastCommitted' OpTime to encompass the
|
|
// 'prepareTimestamp'.
|
|
PrepareHelpers.awaitMajorityCommitted(rst, prepareTimestamp);
|
|
|
|
if (commit) {
|
|
// Commit the prepared transaction on the new primary.
|
|
assert.commandWorked(PrepareHelpers.commitTransaction(session, prepareTimestamp));
|
|
|
|
// Verify the effect of the transaction.
|
|
const doc = newPrimary.getDB(dbName).getCollection(collName).findOne({});
|
|
assert.docEq(newDoc, doc);
|
|
oldDoc = newDoc;
|
|
} else {
|
|
// Abort the prepared transaction on the new primary.
|
|
assert.commandWorked(session.abortTransaction_forTesting());
|
|
|
|
// Verify the effect of the transaction is not applied.
|
|
const doc = newPrimary.getDB(dbName).getCollection(collName).findOne({});
|
|
assert.docEq(oldDoc, doc);
|
|
}
|
|
|
|
primary = rst.getPrimary();
|
|
secondary = rst.getSecondary();
|
|
};
|
|
|
|
[false, true].forEach((failover) => [true, false].forEach((commit) => runTest(failover, commit)));
|
|
|
|
rst.stopSet();
|