diff options
Diffstat (limited to 'jstests/sharding/transactions_snapshot_errors_subsequent_statements.js')
-rw-r--r-- | jstests/sharding/transactions_snapshot_errors_subsequent_statements.js | 188 |
1 files changed, 93 insertions, 95 deletions
diff --git a/jstests/sharding/transactions_snapshot_errors_subsequent_statements.js b/jstests/sharding/transactions_snapshot_errors_subsequent_statements.js index 27855d9bc1a..e83ef670708 100644 --- a/jstests/sharding/transactions_snapshot_errors_subsequent_statements.js +++ b/jstests/sharding/transactions_snapshot_errors_subsequent_statements.js @@ -7,116 +7,114 @@ // // @tags: [requires_sharding, uses_transactions, uses_multi_shard_transaction] (function() { - "use strict"; - - load("jstests/sharding/libs/sharded_transactions_helpers.js"); - - const dbName = "test"; - const collName = "foo"; - const ns = dbName + '.' + collName; - - const kCommandTestCases = [ - {name: "aggregate", command: {aggregate: collName, pipeline: [], cursor: {}}}, - {name: "distinct", command: {distinct: collName, query: {}, key: "_id"}}, - {name: "find", command: {find: collName}}, - { - // findAndModify can only target one shard, even in the two shard case. - name: "findAndModify", - command: {findAndModify: collName, query: {_id: 1}, update: {$set: {x: 1}}} - }, - {name: "insert", command: {insert: collName, documents: [{_id: 1}, {_id: 11}]}}, - { - name: "update", - command: { - update: collName, - updates: [{q: {_id: 1}, u: {$set: {_id: 2}}}, {q: {_id: 11}, u: {$set: {_id: 12}}}] - } - }, - { - name: "delete", - command: - {delete: collName, deletes: [{q: {_id: 2}, limit: 1}, {q: {_id: 12}, limit: 1}]} - }, - // We cannot test killCursors because mongos discards the response from any killCursors - // requests that may be sent to shards. - ]; - - function runTest(st, collName, errorCode, isSharded) { - const session = st.s.startSession(); - const sessionDB = session.getDatabase(dbName); - - for (let commandTestCase of kCommandTestCases) { - const commandName = commandTestCase.name; - const commandBody = commandTestCase.command; - - if (isSharded && commandName === "distinct") { - // Distinct isn't allowed on sharded collections in a multi-document transaction. - print("Skipping distinct test case for sharded collections"); - continue; - } - - // Successfully start a transaction on one shard. - session.startTransaction({readConcern: {level: "snapshot"}}); - assert.commandWorked(sessionDB.runCommand({find: collName, filter: {_id: 15}})); - - // Verify the command must fail on a snapshot error from a subsequent statement. - setFailCommandOnShards(st, {times: 1}, [commandName], errorCode, 1); - const res = assert.commandFailedWithCode(sessionDB.runCommand(commandBody), errorCode); - assert.eq(res.errorLabels, ["TransientTransactionError"]); - - assertNoSuchTransactionOnAllShards( - st, session.getSessionId(), session.getTxnNumber_forTesting()); - assert.commandFailedWithCode(session.abortTransaction_forTesting(), - ErrorCodes.NoSuchTransaction); +"use strict"; + +load("jstests/sharding/libs/sharded_transactions_helpers.js"); + +const dbName = "test"; +const collName = "foo"; +const ns = dbName + '.' + collName; + +const kCommandTestCases = [ + {name: "aggregate", command: {aggregate: collName, pipeline: [], cursor: {}}}, + {name: "distinct", command: {distinct: collName, query: {}, key: "_id"}}, + {name: "find", command: {find: collName}}, + { + // findAndModify can only target one shard, even in the two shard case. + name: "findAndModify", + command: {findAndModify: collName, query: {_id: 1}, update: {$set: {x: 1}}} + }, + {name: "insert", command: {insert: collName, documents: [{_id: 1}, {_id: 11}]}}, + { + name: "update", + command: { + update: collName, + updates: [{q: {_id: 1}, u: {$set: {_id: 2}}}, {q: {_id: 11}, u: {$set: {_id: 12}}}] } + }, + { + name: "delete", + command: {delete: collName, deletes: [{q: {_id: 2}, limit: 1}, {q: {_id: 12}, limit: 1}]} + }, + // We cannot test killCursors because mongos discards the response from any killCursors + // requests that may be sent to shards. +]; + +function runTest(st, collName, errorCode, isSharded) { + const session = st.s.startSession(); + const sessionDB = session.getDatabase(dbName); + + for (let commandTestCase of kCommandTestCases) { + const commandName = commandTestCase.name; + const commandBody = commandTestCase.command; + + if (isSharded && commandName === "distinct") { + // Distinct isn't allowed on sharded collections in a multi-document transaction. + print("Skipping distinct test case for sharded collections"); + continue; + } + + // Successfully start a transaction on one shard. + session.startTransaction({readConcern: {level: "snapshot"}}); + assert.commandWorked(sessionDB.runCommand({find: collName, filter: {_id: 15}})); + + // Verify the command must fail on a snapshot error from a subsequent statement. + setFailCommandOnShards(st, {times: 1}, [commandName], errorCode, 1); + const res = assert.commandFailedWithCode(sessionDB.runCommand(commandBody), errorCode); + assert.eq(res.errorLabels, ["TransientTransactionError"]); + + assertNoSuchTransactionOnAllShards( + st, session.getSessionId(), session.getTxnNumber_forTesting()); + assert.commandFailedWithCode(session.abortTransaction_forTesting(), + ErrorCodes.NoSuchTransaction); } +} - const st = new ShardingTest({shards: 2, mongos: 1, config: 1}); +const st = new ShardingTest({shards: 2, mongos: 1, config: 1}); - enableStaleVersionAndSnapshotRetriesWithinTransactions(st); +enableStaleVersionAndSnapshotRetriesWithinTransactions(st); - jsTestLog("Unsharded transaction"); +jsTestLog("Unsharded transaction"); - assert.writeOK(st.s.getDB(dbName)[collName].insert({_id: 5}, {writeConcern: {w: "majority"}})); - st.ensurePrimaryShard(dbName, st.shard0.shardName); +assert.writeOK(st.s.getDB(dbName)[collName].insert({_id: 5}, {writeConcern: {w: "majority"}})); +st.ensurePrimaryShard(dbName, st.shard0.shardName); - // Single shard case simulates the storage engine discarding an in-use snapshot. - for (let errorCode of kSnapshotErrors) { - runTest(st, collName, errorCode, false /* isSharded */); - } +// Single shard case simulates the storage engine discarding an in-use snapshot. +for (let errorCode of kSnapshotErrors) { + runTest(st, collName, errorCode, false /* isSharded */); +} - assert.commandWorked(st.s.adminCommand({enableSharding: dbName})); - st.ensurePrimaryShard(dbName, st.shard0.shardName); - assert.commandWorked(st.s.adminCommand({shardCollection: ns, key: {_id: 1}})); +assert.commandWorked(st.s.adminCommand({enableSharding: dbName})); +st.ensurePrimaryShard(dbName, st.shard0.shardName); +assert.commandWorked(st.s.adminCommand({shardCollection: ns, key: {_id: 1}})); - // Set up 2 chunks, [minKey, 10), [10, maxKey), each with one document (includes the document - // already inserted). - assert.commandWorked(st.s.adminCommand({split: ns, middle: {_id: 10}})); - assert.writeOK(st.s.getDB(dbName)[collName].insert({_id: 15}, {writeConcern: {w: "majority"}})); +// Set up 2 chunks, [minKey, 10), [10, maxKey), each with one document (includes the document +// already inserted). +assert.commandWorked(st.s.adminCommand({split: ns, middle: {_id: 10}})); +assert.writeOK(st.s.getDB(dbName)[collName].insert({_id: 15}, {writeConcern: {w: "majority"}})); - jsTestLog("One shard transaction"); +jsTestLog("One shard transaction"); - assert.eq(2, st.s.getDB('config').chunks.count({ns: ns, shard: st.shard0.shardName})); - assert.eq(0, st.s.getDB('config').chunks.count({ns: ns, shard: st.shard1.shardName})); +assert.eq(2, st.s.getDB('config').chunks.count({ns: ns, shard: st.shard0.shardName})); +assert.eq(0, st.s.getDB('config').chunks.count({ns: ns, shard: st.shard1.shardName})); - for (let errorCode of kSnapshotErrors) { - runTest(st, collName, errorCode, true /* isSharded */); - } +for (let errorCode of kSnapshotErrors) { + runTest(st, collName, errorCode, true /* isSharded */); +} - jsTestLog("Two shard transaction"); +jsTestLog("Two shard transaction"); - assert.commandWorked( - st.s.adminCommand({moveChunk: ns, find: {_id: 15}, to: st.shard1.shardName})); - assert.eq(1, st.s.getDB('config').chunks.count({ns: ns, shard: st.shard0.shardName})); - assert.eq(1, st.s.getDB('config').chunks.count({ns: ns, shard: st.shard1.shardName})); +assert.commandWorked(st.s.adminCommand({moveChunk: ns, find: {_id: 15}, to: st.shard1.shardName})); +assert.eq(1, st.s.getDB('config').chunks.count({ns: ns, shard: st.shard0.shardName})); +assert.eq(1, st.s.getDB('config').chunks.count({ns: ns, shard: st.shard1.shardName})); - // Multi shard case simulates adding a new participant that can no longer support the already - // chosen read timestamp. - for (let errorCode of kSnapshotErrors) { - runTest(st, collName, errorCode, true /* isSharded */); - } +// Multi shard case simulates adding a new participant that can no longer support the already +// chosen read timestamp. +for (let errorCode of kSnapshotErrors) { + runTest(st, collName, errorCode, true /* isSharded */); +} - disableStaleVersionAndSnapshotRetriesWithinTransactions(st); +disableStaleVersionAndSnapshotRetriesWithinTransactions(st); - st.stop(); +st.stop(); })(); |