diff options
author | Sanika Phanse <sanika.phanse@mongodb.com> | 2022-04-27 20:54:24 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-04-27 21:49:15 +0000 |
commit | 500de2dcb8dacdac28ba3258ff8143883f087337 (patch) | |
tree | 04e15cb9cd25c99af8fce6453da280b42e789ccb | |
parent | d68a849239961b2e59484f5955052a8a80adc00b (diff) | |
download | mongo-500de2dcb8dacdac28ba3258ff8143883f087337.tar.gz |
SERVER-64194 Add test coverage for refreshFromStorageIfNeeded() for a retryable internal transaction with write statements with kUninitializedStmtId
-rw-r--r-- | jstests/sharding/internal_txns/uninitialized_stmt_id_not_saved_in_oplog.js | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/jstests/sharding/internal_txns/uninitialized_stmt_id_not_saved_in_oplog.js b/jstests/sharding/internal_txns/uninitialized_stmt_id_not_saved_in_oplog.js new file mode 100644 index 00000000000..cd019f879fc --- /dev/null +++ b/jstests/sharding/internal_txns/uninitialized_stmt_id_not_saved_in_oplog.js @@ -0,0 +1,113 @@ +/* + * Confirm that retryable writes written with stmtId = -1 do not store stmtId information and that + * this behavior is preserved through the restart of the primary shard & mongos. + * + * @tags: [requires_fcv_60, uses_transactions, requires_persistence] + */ +(function() { +'use strict'; + +load("jstests/sharding/libs/sharded_transactions_helpers.js"); + +const st = new ShardingTest({shards: 1}); +const shard0Primary = st.rs0.getPrimary(); + +const dbName = "testDb"; +const collName = "testColl"; +const ns = dbName + "." + collName; + +// Insert initial data. +assert.commandWorked(st.s.getCollection(ns).insert([{x: 0}])); + +jsTest.log( + "Insert documents in a retryable write with uninitialized and initialized stmtIds. Expect DuplicateKey error upon retry of insert after restarting the mongos and primary shard of command with uninitialized stmtId. Expect command with initialized stmtId to return that it has previously been tried."); +const lsid = { + id: UUID(), + txnNumber: NumberLong(5), + txnUUID: UUID() +}; +const txnNumber = NumberLong(0); +const document = { + _id: 0 +}; + +const lsidWithStmtId = { + id: UUID(), + txnNumber: NumberLong(5), + txnUUID: UUID() +}; +const txnNumberWithStmtId = NumberLong(1); +const documentWithStmtId = { + _id: 1 +}; +const initializedStmtId = NumberInt(1); + +const retryableInsertCommandObjUninitializedStmtId = { + insert: collName, + documents: [document], + lsid: lsid, + txnNumber: txnNumber, + startTransaction: true, + autocommit: false, + stmtId: NumberInt(-1) +}; + +const retryableInsertCommandObjInitializedStmtId = { + insert: collName, + documents: [documentWithStmtId], + lsid: lsidWithStmtId, + txnNumber: txnNumberWithStmtId, + startTransaction: true, + autocommit: false, + stmtId: initializedStmtId +}; + +// Insert both documents, with and without initialized stmtIds. +assert.commandWorked(st.s.getDB(dbName).runCommand(retryableInsertCommandObjUninitializedStmtId)); +assert.commandWorked( + st.s.adminCommand({commitTransaction: 1, lsid: lsid, txnNumber: txnNumber, autocommit: false})); +assert.commandWorked(st.s.getDB(dbName).runCommand(retryableInsertCommandObjInitializedStmtId)); +assert.commandWorked(st.s.adminCommand({ + commitTransaction: 1, + lsid: lsidWithStmtId, + txnNumber: txnNumberWithStmtId, + autocommit: false +})); + +// Confirm documents were inserted. +assert.eq(document, st.s.getCollection(ns).findOne(document)); +assert.eq(documentWithStmtId, st.s.getCollection(ns).findOne(documentWithStmtId)); + +// The applyOps for an uninitialized stmtId should not have a stmtId property. +let oplog = getOplogEntriesForTxn(st.rs0, lsid, txnNumber); +assert(!oplog[0].o.applyOps[0].hasOwnProperty("stmtId")); + +// The applyOps for an initialized stmtId should have a populated stmtId property. +oplog = getOplogEntriesForTxn(st.rs0, lsidWithStmtId, txnNumberWithStmtId); +assert.eq(initializedStmtId, oplog[0].o.applyOps[0].stmtId); + +// Force refresh of primary & mongos. +st.rs0.restart(shard0Primary); +st.rs0.waitForPrimary(); +st.restartMongos(0); + +// Retry the insert command with stmtId = -1. Expect the insert to be unsuccessful. +let res = assert.commandFailedWithCode( + st.s.getDB(dbName).runCommand(retryableInsertCommandObjUninitializedStmtId), + ErrorCodes.DuplicateKey); + +// retriedStmtIds field should not be set. +assert(!res.hasOwnProperty("retriedStmtIds")); + +// Retry insert command with stmtId = 1. Insert should be successful with the retriedStmtIds field +// populated. +res = + assert.commandWorked(st.s.getDB(dbName).runCommand(retryableInsertCommandObjInitializedStmtId)); +assert.eq(initializedStmtId, res.retriedStmtIds[0]); + +// Confirm that documents are in the collection. +assert.eq(document, st.s.getCollection(ns).findOne(document)); +assert.eq(documentWithStmtId, st.s.getCollection(ns).findOne(documentWithStmtId)); + +st.stop(); +})(); |