diff options
Diffstat (limited to 'jstests/noPassthrough/server_transaction_metrics_for_prepared_transactions.js')
-rw-r--r-- | jstests/noPassthrough/server_transaction_metrics_for_prepared_transactions.js | 342 |
1 files changed, 171 insertions, 171 deletions
diff --git a/jstests/noPassthrough/server_transaction_metrics_for_prepared_transactions.js b/jstests/noPassthrough/server_transaction_metrics_for_prepared_transactions.js index 172e9e3e5a9..a41e66dfc2d 100644 --- a/jstests/noPassthrough/server_transaction_metrics_for_prepared_transactions.js +++ b/jstests/noPassthrough/server_transaction_metrics_for_prepared_transactions.js @@ -3,175 +3,175 @@ * @tags: [uses_transactions, uses_prepare_transaction] */ (function() { - "use strict"; - load("jstests/core/txns/libs/prepare_helpers.js"); - load("jstests/replsets/rslib.js"); - - /** - * Verifies that the serverStatus response has the fields that we expect. - */ - function verifyServerStatusFields(serverStatusResponse) { - assert(serverStatusResponse.hasOwnProperty("transactions"), - "Expected the serverStatus response to have a 'transactions' field: " + - tojson(serverStatusResponse)); - assert(serverStatusResponse.transactions.hasOwnProperty("totalPrepared"), - "Expected the serverStatus response to have a 'totalPrepared' field: " + - tojson(serverStatusResponse)); - assert(serverStatusResponse.transactions.hasOwnProperty("totalPreparedThenCommitted"), - "Expected the serverStatus response to have a 'totalPreparedThenCommitted' field: " + - tojson(serverStatusResponse)); - assert(serverStatusResponse.transactions.hasOwnProperty("totalPreparedThenAborted"), - "Expected the serverStatus response to have a 'totalPreparedThenAborted' field: " + - tojson(serverStatusResponse)); - assert(serverStatusResponse.transactions.hasOwnProperty("currentPrepared"), - "Expected the serverStatus response to have a 'currentPrepared' field: " + - tojson(serverStatusResponse)); - } - - /** - * Verifies that the given value of the server status response is incremented in the way - * we expect. - */ - function verifyServerStatusChange(initialStats, newStats, valueName, expectedIncrement) { - assert.eq(initialStats[valueName] + expectedIncrement, - newStats[valueName], - "expected " + valueName + " to increase by " + expectedIncrement); - } - - /** - * Verifies that the timestamp of the oldest active transaction in the transactions table - * is greater than the lower bound and less than or equal to the upper bound. - */ - function verifyOldestActiveTransactionTimestamp(testDB, lowerBound, upperBound) { - let res = assert.commandWorked( - testDB.getSiblingDB("config").getCollection("transactions").runCommand("find", { - "filter": {"state": {"$in": ["prepared", "inProgress"]}}, - "sort": {"startOpTime": 1}, - "readConcern": {"level": "local"}, - "limit": 1 - })); - - let entry = res.cursor.firstBatch[0]; - assert.neq(undefined, entry); - - assert.lt(lowerBound, - entry.startOpTime.ts, - "oldest active transaction timestamp should be greater than the lower bound"); - assert.lte( - entry.startOpTime.ts, - upperBound, - "oldest active transaction timestamp should be less than or equal to the upper bound"); - } - - // Set up the replica set. - const rst = new ReplSetTest({nodes: 1}); - - rst.startSet(); - rst.initiate(); - const primary = rst.getPrimary(); - - // Set up the test database. - const dbName = "test"; - const collName = "server_transactions_metrics_for_prepared_transactions"; - const testDB = primary.getDB(dbName); - testDB.runCommand({drop: collName, writeConcern: {w: "majority"}}); - assert.commandWorked(testDB.runCommand({create: collName, writeConcern: {w: "majority"}})); - - // Start the session. - const sessionOptions = {causalConsistency: false}; - const session = testDB.getMongo().startSession(sessionOptions); - const sessionDb = session.getDatabase(dbName); - const sessionColl = sessionDb[collName]; - - // Get state of server status before the transaction. - const initialStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1})); - verifyServerStatusFields(initialStatus); - - // Test server metrics for a prepared transaction that is committed. - jsTest.log("Prepare a transaction and then commit it"); - - const doc1 = {_id: 1, x: 1}; - - // Start transaction and prepare transaction. - session.startTransaction(); - assert.commandWorked(sessionColl.insert(doc1)); - - const opTimeBeforePrepareForCommit = getLastOpTime(primary); - const prepareTimestampForCommit = PrepareHelpers.prepareTransaction(session); - - // Verify the total and current prepared transaction counter is updated and the oldest active - // oplog entry timestamp is shown. - let newStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1})); - verifyServerStatusFields(newStatus); - verifyServerStatusChange( - initialStatus.transactions, newStatus.transactions, "totalPrepared", 1); - verifyServerStatusChange( - initialStatus.transactions, newStatus.transactions, "currentPrepared", 1); - - // Verify that the prepare entry has the oldest timestamp of any active transaction - // in the transactions table. - verifyOldestActiveTransactionTimestamp( - testDB, opTimeBeforePrepareForCommit.ts, prepareTimestampForCommit); - - // Verify the total prepared and committed transaction counters are updated after a commit - // and that the current prepared counter is decremented. - PrepareHelpers.commitTransaction(session, prepareTimestampForCommit); - newStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1})); - verifyServerStatusFields(newStatus); - verifyServerStatusChange( - initialStatus.transactions, newStatus.transactions, "totalPreparedThenCommitted", 1); - verifyServerStatusChange( - initialStatus.transactions, newStatus.transactions, "currentPrepared", 0); - - // Verify that other prepared transaction metrics have not changed. - verifyServerStatusChange( - initialStatus.transactions, newStatus.transactions, "totalPreparedThenAborted", 0); - verifyServerStatusChange( - initialStatus.transactions, newStatus.transactions, "totalPrepared", 1); - - // Test server metrics for a prepared transaction that is aborted. - jsTest.log("Prepare a transaction and then abort it"); - - const doc2 = {_id: 2, x: 2}; - - // Start transaction and prepare transaction. - session.startTransaction(); - assert.commandWorked(sessionColl.insert(doc2)); - - const opTimeBeforePrepareForAbort = getLastOpTime(primary); - const prepareTimestampForAbort = PrepareHelpers.prepareTransaction(session); - - // Verify that the total and current prepared counter is updated and the oldest active oplog - // entry timestamp is shown. - newStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1})); - verifyServerStatusFields(newStatus); - verifyServerStatusChange( - initialStatus.transactions, newStatus.transactions, "totalPrepared", 2); - verifyServerStatusChange( - initialStatus.transactions, newStatus.transactions, "currentPrepared", 1); - - // Verify that the prepare entry has the oldest timestamp of any active transaction - // in the transactions table. - verifyOldestActiveTransactionTimestamp( - testDB, opTimeBeforePrepareForAbort.ts, prepareTimestampForAbort); - - // Verify the total prepared and aborted transaction counters are updated after an abort and the - // current prepared counter is decremented. - assert.commandWorked(session.abortTransaction_forTesting()); - newStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1})); - verifyServerStatusFields(newStatus); - verifyServerStatusChange( - initialStatus.transactions, newStatus.transactions, "totalPreparedThenAborted", 1); - verifyServerStatusChange( - initialStatus.transactions, newStatus.transactions, "currentPrepared", 0); - - // Verify that other prepared transaction metrics have not changed. - verifyServerStatusChange( - initialStatus.transactions, newStatus.transactions, "totalPreparedThenCommitted", 1); - verifyServerStatusChange( - initialStatus.transactions, newStatus.transactions, "totalPrepared", 2); - - // End the session and stop the replica set. - session.endSession(); - rst.stopSet(); +"use strict"; +load("jstests/core/txns/libs/prepare_helpers.js"); +load("jstests/replsets/rslib.js"); + +/** + * Verifies that the serverStatus response has the fields that we expect. + */ +function verifyServerStatusFields(serverStatusResponse) { + assert(serverStatusResponse.hasOwnProperty("transactions"), + "Expected the serverStatus response to have a 'transactions' field: " + + tojson(serverStatusResponse)); + assert(serverStatusResponse.transactions.hasOwnProperty("totalPrepared"), + "Expected the serverStatus response to have a 'totalPrepared' field: " + + tojson(serverStatusResponse)); + assert(serverStatusResponse.transactions.hasOwnProperty("totalPreparedThenCommitted"), + "Expected the serverStatus response to have a 'totalPreparedThenCommitted' field: " + + tojson(serverStatusResponse)); + assert(serverStatusResponse.transactions.hasOwnProperty("totalPreparedThenAborted"), + "Expected the serverStatus response to have a 'totalPreparedThenAborted' field: " + + tojson(serverStatusResponse)); + assert(serverStatusResponse.transactions.hasOwnProperty("currentPrepared"), + "Expected the serverStatus response to have a 'currentPrepared' field: " + + tojson(serverStatusResponse)); +} + +/** + * Verifies that the given value of the server status response is incremented in the way + * we expect. + */ +function verifyServerStatusChange(initialStats, newStats, valueName, expectedIncrement) { + assert.eq(initialStats[valueName] + expectedIncrement, + newStats[valueName], + "expected " + valueName + " to increase by " + expectedIncrement); +} + +/** + * Verifies that the timestamp of the oldest active transaction in the transactions table + * is greater than the lower bound and less than or equal to the upper bound. + */ +function verifyOldestActiveTransactionTimestamp(testDB, lowerBound, upperBound) { + let res = assert.commandWorked( + testDB.getSiblingDB("config").getCollection("transactions").runCommand("find", { + "filter": {"state": {"$in": ["prepared", "inProgress"]}}, + "sort": {"startOpTime": 1}, + "readConcern": {"level": "local"}, + "limit": 1 + })); + + let entry = res.cursor.firstBatch[0]; + assert.neq(undefined, entry); + + assert.lt(lowerBound, + entry.startOpTime.ts, + "oldest active transaction timestamp should be greater than the lower bound"); + assert.lte( + entry.startOpTime.ts, + upperBound, + "oldest active transaction timestamp should be less than or equal to the upper bound"); +} + +// Set up the replica set. +const rst = new ReplSetTest({nodes: 1}); + +rst.startSet(); +rst.initiate(); +const primary = rst.getPrimary(); + +// Set up the test database. +const dbName = "test"; +const collName = "server_transactions_metrics_for_prepared_transactions"; +const testDB = primary.getDB(dbName); +testDB.runCommand({drop: collName, writeConcern: {w: "majority"}}); +assert.commandWorked(testDB.runCommand({create: collName, writeConcern: {w: "majority"}})); + +// Start the session. +const sessionOptions = { + causalConsistency: false +}; +const session = testDB.getMongo().startSession(sessionOptions); +const sessionDb = session.getDatabase(dbName); +const sessionColl = sessionDb[collName]; + +// Get state of server status before the transaction. +const initialStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1})); +verifyServerStatusFields(initialStatus); + +// Test server metrics for a prepared transaction that is committed. +jsTest.log("Prepare a transaction and then commit it"); + +const doc1 = { + _id: 1, + x: 1 +}; + +// Start transaction and prepare transaction. +session.startTransaction(); +assert.commandWorked(sessionColl.insert(doc1)); + +const opTimeBeforePrepareForCommit = getLastOpTime(primary); +const prepareTimestampForCommit = PrepareHelpers.prepareTransaction(session); + +// Verify the total and current prepared transaction counter is updated and the oldest active +// oplog entry timestamp is shown. +let newStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1})); +verifyServerStatusFields(newStatus); +verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "totalPrepared", 1); +verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "currentPrepared", 1); + +// Verify that the prepare entry has the oldest timestamp of any active transaction +// in the transactions table. +verifyOldestActiveTransactionTimestamp( + testDB, opTimeBeforePrepareForCommit.ts, prepareTimestampForCommit); + +// Verify the total prepared and committed transaction counters are updated after a commit +// and that the current prepared counter is decremented. +PrepareHelpers.commitTransaction(session, prepareTimestampForCommit); +newStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1})); +verifyServerStatusFields(newStatus); +verifyServerStatusChange( + initialStatus.transactions, newStatus.transactions, "totalPreparedThenCommitted", 1); +verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "currentPrepared", 0); + +// Verify that other prepared transaction metrics have not changed. +verifyServerStatusChange( + initialStatus.transactions, newStatus.transactions, "totalPreparedThenAborted", 0); +verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "totalPrepared", 1); + +// Test server metrics for a prepared transaction that is aborted. +jsTest.log("Prepare a transaction and then abort it"); + +const doc2 = { + _id: 2, + x: 2 +}; + +// Start transaction and prepare transaction. +session.startTransaction(); +assert.commandWorked(sessionColl.insert(doc2)); + +const opTimeBeforePrepareForAbort = getLastOpTime(primary); +const prepareTimestampForAbort = PrepareHelpers.prepareTransaction(session); + +// Verify that the total and current prepared counter is updated and the oldest active oplog +// entry timestamp is shown. +newStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1})); +verifyServerStatusFields(newStatus); +verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "totalPrepared", 2); +verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "currentPrepared", 1); + +// Verify that the prepare entry has the oldest timestamp of any active transaction +// in the transactions table. +verifyOldestActiveTransactionTimestamp( + testDB, opTimeBeforePrepareForAbort.ts, prepareTimestampForAbort); + +// Verify the total prepared and aborted transaction counters are updated after an abort and the +// current prepared counter is decremented. +assert.commandWorked(session.abortTransaction_forTesting()); +newStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1})); +verifyServerStatusFields(newStatus); +verifyServerStatusChange( + initialStatus.transactions, newStatus.transactions, "totalPreparedThenAborted", 1); +verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "currentPrepared", 0); + +// Verify that other prepared transaction metrics have not changed. +verifyServerStatusChange( + initialStatus.transactions, newStatus.transactions, "totalPreparedThenCommitted", 1); +verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "totalPrepared", 2); + +// End the session and stop the replica set. +session.endSession(); +rst.stopSet(); }()); |