/** * Tests for making sure that retried writes will wait properly for writeConcern. * * @tags: [uses_transactions, uses_prepare_transaction] */ import {ReplSetTest} from "jstests/libs/replsettest.js"; import {runWriteConcernRetryabilityTest} from "jstests/libs/write_concern_util.js"; const kNodes = 2; let replTest = new ReplSetTest({nodes: kNodes}); replTest.startSet({verbose: 1}); replTest.initiate(); let priConn = replTest.getPrimary(); let secConn = replTest.getSecondary(); // Stopping replication on secondaries can take up to 5 seconds normally. Set a small oplog // getMore timeout so the test runs faster. assert.commandWorked(secConn.adminCommand({configureFailPoint: "setSmallOplogGetMoreMaxTimeMS", mode: "alwaysOn"})); let lsid = UUID(); // Start at an arbitrary txnNumber. let txnNumber = 31; txnNumber++; runWriteConcernRetryabilityTest( priConn, secConn, { insert: "user", documents: [{_id: 10}, {_id: 30}], ordered: false, lsid: {id: lsid}, txnNumber: NumberLong(txnNumber), writeConcern: {w: "majority", wtimeout: 200}, }, kNodes, ); txnNumber++; runWriteConcernRetryabilityTest( priConn, secConn, { update: "user", updates: [{q: {_id: 10}, u: {$inc: {x: 1}}}], ordered: false, lsid: {id: lsid}, txnNumber: NumberLong(txnNumber), writeConcern: {w: "majority", wtimeout: 200}, }, kNodes, ); txnNumber++; runWriteConcernRetryabilityTest( priConn, secConn, { delete: "user", deletes: [ {q: {x: 1}, limit: 1}, {q: {y: 1}, limit: 1}, ], ordered: false, lsid: {id: lsid}, txnNumber: NumberLong(txnNumber), writeConcern: {w: "majority", wtimeout: 200}, }, kNodes, ); txnNumber++; runWriteConcernRetryabilityTest( priConn, secConn, { findAndModify: "user", query: {_id: 60}, update: {$inc: {x: 1}}, new: true, upsert: true, lsid: {id: lsid}, txnNumber: NumberLong(txnNumber), writeConcern: {w: "majority", wtimeout: 200}, }, kNodes, ); txnNumber++; runWriteConcernRetryabilityTest( priConn, secConn, { commitTransaction: 1, lsid: {id: lsid}, txnNumber: NumberLong(txnNumber), autocommit: false, writeConcern: {w: "majority", wtimeout: 200}, }, kNodes, "admin", function (conn) { assert.commandWorked( conn.getDB("test").runCommand({ insert: "user", documents: [{_id: 80}, {_id: 90}], ordered: false, lsid: {id: lsid}, txnNumber: NumberLong(txnNumber), readConcern: {level: "snapshot"}, autocommit: false, startTransaction: true, }), ); }, ); txnNumber++; runWriteConcernRetryabilityTest( priConn, secConn, { prepareTransaction: 1, lsid: {id: lsid}, txnNumber: NumberLong(txnNumber), autocommit: false, writeConcern: {w: "majority", wtimeout: 200}, }, kNodes, "admin", function (conn) { assert.commandWorked( conn.getDB("test").runCommand({ insert: "user", documents: [{_id: 100}, {_id: 110}], ordered: false, lsid: {id: lsid}, txnNumber: NumberLong(txnNumber), readConcern: {level: "snapshot"}, autocommit: false, startTransaction: true, }), ); }, ); assert.commandWorked( priConn.adminCommand({ abortTransaction: 1, lsid: {id: lsid}, txnNumber: NumberLong(txnNumber), autocommit: false, writeConcern: {w: "majority"}, }), ); txnNumber++; runWriteConcernRetryabilityTest( priConn, secConn, { abortTransaction: 1, lsid: {id: lsid}, txnNumber: NumberLong(txnNumber), autocommit: false, writeConcern: {w: "majority", wtimeout: 200}, }, kNodes, "admin", function (conn) { assert.commandWorked( conn.getDB("test").runCommand({ insert: "user", documents: [{_id: 120}, {_id: 130}], ordered: false, lsid: {id: lsid}, txnNumber: NumberLong(txnNumber), readConcern: {level: "snapshot"}, autocommit: false, startTransaction: true, }), ); assert.commandWorked( conn.adminCommand({ prepareTransaction: 1, lsid: {id: lsid}, txnNumber: NumberLong(txnNumber), autocommit: false, writeConcern: {w: "majority"}, }), ); }, ); txnNumber++; assert.commandWorked( priConn.getDB("test").runCommand({ insert: "user", documents: [{_id: 140}, {_id: 150}], ordered: false, lsid: {id: lsid}, txnNumber: NumberLong(txnNumber), readConcern: {level: "snapshot"}, autocommit: false, startTransaction: true, }), ); const prepareTS = assert.commandWorked( priConn.adminCommand({ prepareTransaction: 1, lsid: {id: lsid}, txnNumber: NumberLong(txnNumber), autocommit: false, writeConcern: {w: "majority"}, }), ).prepareTimestamp; runWriteConcernRetryabilityTest( priConn, secConn, { commitTransaction: 1, commitTimestamp: prepareTS, lsid: {id: lsid}, txnNumber: NumberLong(txnNumber), autocommit: false, writeConcern: {w: "majority", wtimeout: 200}, }, kNodes, "admin", ); replTest.stopSet();