mirror of
https://github.com/mongodb/mongo.git
synced 2024-12-01 09:32:32 +01:00
91 lines
3.4 KiB
JavaScript
91 lines
3.4 KiB
JavaScript
/**
|
|
* Test that starting transactions and running commitTransaction and abortTransaction commands are
|
|
* not allowed on replica set secondaries.
|
|
*
|
|
* @tags: [uses_transactions]
|
|
*/
|
|
(function() {
|
|
"use strict";
|
|
|
|
const dbName = "test";
|
|
const collName = "transactions_on_secondaries_not_allowed";
|
|
|
|
const rst = new ReplSetTest({name: collName, nodes: 2});
|
|
rst.startSet({verbose: 3});
|
|
// We want a stable topology, so make the secondary unelectable.
|
|
let config = rst.getReplSetConfig();
|
|
config.members[1].priority = 0;
|
|
rst.initiate(config);
|
|
|
|
const primary = rst.getPrimary();
|
|
const secondary = rst.getSecondary();
|
|
const secondaryTestDB = secondary.getDB(dbName);
|
|
|
|
// Do an initial write so we have something to find.
|
|
const initialDoc = {
|
|
_id: 0
|
|
};
|
|
assert.commandWorked(primary.getDB(dbName)[collName].insert(initialDoc));
|
|
rst.awaitLastOpCommitted();
|
|
|
|
// Disable the best-effort check for primary-ness in the service entry point, so that we
|
|
// exercise the real check for primary-ness in TransactionParticipant::beginOrContinue.
|
|
assert.commandWorked(secondary.adminCommand(
|
|
{configureFailPoint: "skipCheckingForNotPrimaryInCommandDispatch", mode: "alwaysOn"}));
|
|
|
|
// Initiate a session on the secondary.
|
|
const sessionOptions = {
|
|
causalConsistency: false,
|
|
retryWrites: true
|
|
};
|
|
const session = secondaryTestDB.getMongo().startSession(sessionOptions);
|
|
const sessionDb = session.getDatabase(dbName);
|
|
|
|
/**
|
|
* Test starting a transaction and issuing a commitTransaction command.
|
|
*/
|
|
|
|
jsTestLog("Start a read-only transaction on the secondary.");
|
|
session.startTransaction({readConcern: {level: "snapshot"}});
|
|
|
|
// Try to read a document (the first statement in the transaction) and verify that this fails.
|
|
assert.commandFailedWithCode(sessionDb.runCommand({find: collName}), ErrorCodes.NotWritablePrimary);
|
|
|
|
// The check for "NotWritablePrimary" supercedes the check for "NoSuchTransaction" in this case.
|
|
jsTestLog("Make sure we are not allowed to run the commitTransaction command on the secondary.");
|
|
assert.commandFailedWithCode(session.commitTransaction_forTesting(), ErrorCodes.NotWritablePrimary);
|
|
|
|
/**
|
|
* Test starting a transaction and issuing an abortTransaction command.
|
|
*/
|
|
|
|
jsTestLog("Start a different read-only transaction on the secondary.");
|
|
session.startTransaction({readConcern: {level: "snapshot"}});
|
|
|
|
// Try to read a document (the first statement in the transaction) and verify that this fails.
|
|
assert.commandFailedWithCode(sessionDb.runCommand({find: collName}), ErrorCodes.NotWritablePrimary);
|
|
|
|
// The check for "NotWritablePrimary" supercedes the check for "NoSuchTransaction" in this case.
|
|
jsTestLog("Make sure we are not allowed to run the abortTransaction command on the secondary.");
|
|
assert.commandFailedWithCode(session.abortTransaction_forTesting(), ErrorCodes.NotWritablePrimary);
|
|
|
|
/**
|
|
* Test starting a retryable write.
|
|
*/
|
|
|
|
jsTestLog("Start a retryable write");
|
|
assert.commandFailedWithCode(sessionDb.foo.insert({_id: 0}), ErrorCodes.NotWritablePrimary);
|
|
|
|
/**
|
|
* Test starting a read with txnNumber, but without autocommit. This fails in general because
|
|
* txnNumber isn't supported for the find command outside of transactions, but we check that
|
|
* this fails on a secondary.
|
|
*/
|
|
|
|
jsTestLog("Start a read with txnNumber but without autocommit");
|
|
assert.commandFailedWithCode(sessionDb.runCommand({find: 'foo', txnNumber: NumberLong(10)}), 50768);
|
|
|
|
session.endSession();
|
|
rst.stopSet(undefined, false, {skipValidation: true});
|
|
}());
|