Files
mongo/jstests/core/txns/create_collection_parallel.js

185 lines
8.6 KiB
JavaScript

/**
* Tests parallel transactions with createCollections.
*
* @tags: [
* uses_transactions,
* ]
*/
(function() {
"use strict";
load("jstests/libs/create_collection_txn_helpers.js");
load("jstests/libs/auto_retry_transaction_in_sharding.js");
const dbName = 'test_txns_create_collection_parallel';
function runParallelCollectionCreateTest(command, explicitCreate) {
const dbName = 'test_txns_create_collection_parallel';
const collName = "create_new_collection";
const distinctCollName = collName + "_second";
const session = db.getMongo().getDB(dbName).getMongo().startSession();
const secondSession = db.getMongo().getDB(dbName).getMongo().startSession();
let sessionDB = session.getDatabase(dbName);
let secondSessionDB = secondSession.getDatabase(dbName);
let sessionColl = sessionDB[collName];
sessionColl.drop({writeConcern: {w: "majority"}});
let distinctSessionColl = sessionDB[distinctCollName];
distinctSessionColl.drop({writeConcern: {w: "majority"}});
jsTest.log("Testing duplicate createCollections, second createCollection fails");
session.startTransaction({writeConcern: {w: "majority"}}); // txn 1
secondSession.startTransaction({writeConcern: {w: "majority"}}); // txn 2
retryOnceOnTransientAndRestartTxnOnMongos(session, () => {
createCollAndCRUDInTxn(sessionDB, collName, command, explicitCreate);
}, {writeConcern: {w: "majority"}});
jsTest.log("Committing transaction 1");
session.commitTransaction();
assert.eq(sessionColl.find({}).itcount(), 1);
assert.commandFailedWithCode(secondSessionDB.runCommand({create: collName}),
ErrorCodes.NamespaceExists);
assert.commandFailedWithCode(secondSession.abortTransaction_forTesting(),
ErrorCodes.NoSuchTransaction);
sessionColl.drop({writeConcern: {w: "majority"}});
distinctSessionColl.drop({writeConcern: {w: "majority"}});
jsTest.log("Testing duplicate createCollections, where failing createCollection performs a " +
"successful operation earlier in the transaction.");
session.startTransaction({writeConcern: {w: "majority"}}); // txn 1
secondSession.startTransaction({writeConcern: {w: "majority"}}); // txn 2
retryOnceOnTransientAndRestartTxnOnMongos(secondSession, () => {
createCollAndCRUDInTxn(secondSessionDB, distinctCollName, command, explicitCreate);
}, {writeConcern: {w: "majority"}});
retryOnceOnTransientAndRestartTxnOnMongos(session, () => {
createCollAndCRUDInTxn(sessionDB, collName, command, explicitCreate);
}, {writeConcern: {w: "majority"}});
jsTest.log("Committing transaction 1");
session.commitTransaction();
assert.eq(sessionColl.find({}).itcount(), 1);
assert.commandFailedWithCode(secondSessionDB.runCommand({create: collName}),
ErrorCodes.NamespaceExists);
assert.commandFailedWithCode(secondSession.abortTransaction_forTesting(),
ErrorCodes.NoSuchTransaction);
assert.eq(distinctSessionColl.find({}).itcount(), 0);
sessionColl.drop({writeConcern: {w: "majority"}});
distinctSessionColl.drop({writeConcern: {w: "majority"}});
jsTest.log("Testing duplicate createCollections, one inside and one outside a txn");
session.startTransaction({writeConcern: {w: "majority"}});
retryOnceOnTransientAndRestartTxnOnMongos(session, () => {
createCollAndCRUDInTxn(sessionDB, collName, command, explicitCreate);
}, {writeConcern: {w: "majority"}});
assert.commandWorked(secondSessionDB.runCommand({create: collName})); // outside txn
assert.commandWorked(secondSessionDB.getCollection(collName).insert({a: 1}));
jsTest.log("Committing transaction (SHOULD FAIL)");
assert.commandFailedWithCode(session.commitTransaction_forTesting(), ErrorCodes.WriteConflict);
assert.eq(sessionColl.find({}).itcount(), 1);
sessionColl.drop({writeConcern: {w: "majority"}});
jsTest.log(
"Testing duplicate createCollections in parallel, both attempt to commit, second to commit fails");
secondSession.startTransaction({writeConcern: {w: "majority"}}); // txn 2
retryOnceOnTransientAndRestartTxnOnMongos(secondSession, () => {
createCollAndCRUDInTxn(
secondSession.getDatabase(dbName), collName, command, explicitCreate);
}, {writeConcern: {w: "majority"}});
session.startTransaction({writeConcern: {w: "majority"}}); // txn 1
retryOnceOnTransientAndRestartTxnOnMongos(session, () => {
createCollAndCRUDInTxn(sessionDB, collName, command, explicitCreate);
}, {writeConcern: {w: "majority"}});
jsTest.log("Committing transaction 2");
secondSession.commitTransaction();
jsTest.log("Committing transaction 1 (SHOULD FAIL)");
assert.commandFailedWithCode(session.commitTransaction_forTesting(), ErrorCodes.WriteConflict);
assert.eq(sessionColl.find({}).itcount(), 1);
sessionColl.drop({writeConcern: {w: "majority"}});
jsTest.log("Testing duplicate createCollections which implicitly create databases in parallel" +
", both attempt to commit, second to commit fails");
assert.commandWorked(sessionDB.dropDatabase());
secondSession.startTransaction({writeConcern: {w: "majority"}}); // txn 2
retryOnceOnTransientAndRestartTxnOnMongos(secondSession, () => {
createCollAndCRUDInTxn(
secondSession.getDatabase(dbName), collName, command, explicitCreate);
}, {writeConcern: {w: "majority"}});
session.startTransaction({writeConcern: {w: "majority"}}); // txn 1
retryOnceOnTransientAndRestartTxnOnMongos(session, () => {
createCollAndCRUDInTxn(sessionDB, collName, command, explicitCreate);
}, {writeConcern: {w: "majority"}});
jsTest.log("Committing transaction 2");
secondSession.commitTransaction();
jsTest.log("Committing transaction 1 (SHOULD FAIL)");
assert.commandFailedWithCode(session.commitTransaction_forTesting(), ErrorCodes.WriteConflict);
assert.eq(sessionColl.find({}).itcount(), 1);
sessionColl.drop({writeConcern: {w: "majority"}});
distinctSessionColl.drop({writeConcern: {w: "majority"}});
jsTest.log("Testing createCollection conflict during commit, where the conflict rolls back a " +
"previously committed collection.");
secondSession.startTransaction({writeConcern: {w: "majority"}}); // txn 2
retryOnceOnTransientAndRestartTxnOnMongos(secondSession, () => {
createCollAndCRUDInTxn(
secondSession.getDatabase(dbName), collName, command, explicitCreate);
}, {writeConcern: {w: "majority"}});
session.startTransaction({writeConcern: {w: "majority"}}); // txn 1
retryOnceOnTransientAndRestartTxnOnMongos(session, () => {
createCollAndCRUDInTxn(
sessionDB, distinctCollName, command, explicitCreate); // does not conflict
createCollAndCRUDInTxn(sessionDB, collName, command, explicitCreate); // conflicts
}, {writeConcern: {w: "majority"}});
jsTest.log("Committing transaction 2");
secondSession.commitTransaction();
jsTest.log("Committing transaction 1 (SHOULD FAIL)");
assert.commandFailedWithCode(session.commitTransaction_forTesting(), ErrorCodes.WriteConflict);
assert.eq(sessionColl.find({}).itcount(), 1);
assert.eq(distinctSessionColl.find({}).itcount(), 0);
sessionColl.drop({writeConcern: {w: "majority"}});
distinctSessionColl.drop({writeConcern: {w: "majority"}});
jsTest.log("Testing distinct createCollections in parallel, both successfully commit.");
session.startTransaction({writeConcern: {w: "majority"}}); // txn 1
retryOnceOnTransientAndRestartTxnOnMongos(session, () => {
createCollAndCRUDInTxn(sessionDB, collName, command, explicitCreate);
}, {writeConcern: {w: "majority"}});
secondSession.startTransaction({writeConcern: {w: "majority"}}); // txn 2
retryOnceOnTransientAndRestartTxnOnMongos(secondSession, () => {
createCollAndCRUDInTxn(secondSessionDB, distinctCollName, command, explicitCreate);
}, {writeConcern: {w: "majority"}});
session.commitTransaction();
secondSession.commitTransaction();
secondSession.endSession();
session.endSession();
}
runParallelCollectionCreateTest("insert", true /*explicitCreate*/);
runParallelCollectionCreateTest("insert", false /*explicitCreate*/);
runParallelCollectionCreateTest("update", true /*explicitCreate*/);
runParallelCollectionCreateTest("update", false /*explicitCreate*/);
runParallelCollectionCreateTest("findAndModify", true /*explicitCreate*/);
runParallelCollectionCreateTest("findAndModify", false /*explicitCreate*/);
}());