diff options
author | Vesselina Ratcheva <vesselina.ratcheva@10gen.com> | 2019-06-06 16:44:48 -0400 |
---|---|---|
committer | Vesselina Ratcheva <vesselina.ratcheva@10gen.com> | 2019-06-12 14:17:26 -0400 |
commit | 259bd089d0265ac510acbe4512eb706cd553562b (patch) | |
tree | 579f5e948821ae242325ad5ece6cd166d7f1244a /jstests | |
parent | dfa8658c18142c560447c7bf6f34a6f788593d28 (diff) | |
download | mongo-259bd089d0265ac510acbe4512eb706cd553562b.tar.gz |
SERVER-41207 Test committing prepared transactions after stepdown due to reconfig
Diffstat (limited to 'jstests')
3 files changed, 101 insertions, 0 deletions
diff --git a/jstests/replsets/libs/prepare_failover_due_to_reconfig.js b/jstests/replsets/libs/prepare_failover_due_to_reconfig.js new file mode 100644 index 00000000000..cf5b4e58fd8 --- /dev/null +++ b/jstests/replsets/libs/prepare_failover_due_to_reconfig.js @@ -0,0 +1,72 @@ +"use strict"; + +/** + * Library used to test that prepared transactions survive failovers due to reconfig. + */ + +var testPrepareFailoverDueToReconfig = function(name, reconfigOnPrimary) { + load("jstests/core/txns/libs/prepare_helpers.js"); + + const dbName = "test"; + const collName = name; + + const rst = new ReplSetTest({name: name, nodes: 2}); + const nodes = rst.nodeList(); + + rst.startSet(); + rst.initiate({ + "_id": name, + "members": [ + {/* primary */ "_id": 0, "host": nodes[0]}, + {/* secondary */ "_id": 1, "host": nodes[1], "priority": 0} + ] + }); + + const primary = rst.getPrimary(); + const secondary = rst.getSecondary(); + + const testDB = primary.getDB(dbName); + const testColl = testDB.getCollection(collName); + + const oldDoc = {_id: 42, "is": "old"}; + const newDoc = {_id: 42, "is": "new"}; + + // First create the collection. + assert.commandWorked(testColl.insert(oldDoc)); + + const session = primary.startSession(); + const sessionDB = session.getDatabase(dbName); + const sessionColl = sessionDB.getCollection(collName); + + session.startTransaction(); + assert.commandWorked(sessionColl.update(oldDoc, newDoc)); + + // Prepare a transaction. This will be replicated to the secondary. + const prepareTimestamp = PrepareHelpers.prepareTransaction(session); + + // Now reconfig to force a failover. + let config = rst.getReplSetConfigFromNode(); + + config.members[0].priority = 0; + config.members[1].priority = 1; + config.version++; + + // Run the reconfig command on whichever node the caller targeted. + const reconfigTarget = reconfigOnPrimary ? primary : secondary; + assert.commandWorked(reconfigTarget.adminCommand({replSetReconfig: config, force: true})); + rst.waitForState(primary, ReplSetTest.State.SECONDARY); + + // Wait for the old secondary to become the new primary. + const newPrimary = rst.getPrimary(); + assert.neq(primary, newPrimary, "failover did not occur"); + + // Commit the prepared transaction on the new primary. + const newSession = new _DelegatingDriverSession(newPrimary, session); + assert.commandWorked(PrepareHelpers.commitTransaction(newSession, prepareTimestamp)); + + // Verify the effect of the transaction. + const doc = newPrimary.getDB(dbName).getCollection(collName).findOne({}); + assert.docEq(newDoc, doc); + + rst.stopSet(); +};
\ No newline at end of file diff --git a/jstests/replsets/prepare_survives_primary_reconfig_failover.js b/jstests/replsets/prepare_survives_primary_reconfig_failover.js new file mode 100644 index 00000000000..8db3322b796 --- /dev/null +++ b/jstests/replsets/prepare_survives_primary_reconfig_failover.js @@ -0,0 +1,14 @@ +/** + * Tests that prepared transactions can safely be committed after a failover due to reconfig. We + * issue the reconfig command directly against the primary in this test. + * + * @tags: [uses_transactions, uses_prepare_transaction] + */ +(function() { + "use strict"; + load("jstests/replsets/libs/prepare_failover_due_to_reconfig.js"); + + let testName = "prepare_survives_primary_reconfig_failover"; + + testPrepareFailoverDueToReconfig(testName, /* reconfigOnPrimary */ true); +})(); diff --git a/jstests/replsets/prepare_survives_reconfig_via_heartbeat_failover.js b/jstests/replsets/prepare_survives_reconfig_via_heartbeat_failover.js new file mode 100644 index 00000000000..bf4a0c565a9 --- /dev/null +++ b/jstests/replsets/prepare_survives_reconfig_via_heartbeat_failover.js @@ -0,0 +1,15 @@ +/** + * Tests that prepared transactions can safely be committed after a failover due to reconfig. We + * issue the reconfig command against the secondary in this test, so that the primary can learn of + * the new config via a heartbeat from that secondary. + * + * @tags: [uses_transactions, uses_prepare_transaction] + */ +(function() { + "use strict"; + load("jstests/replsets/libs/prepare_failover_due_to_reconfig.js"); + + let testName = "prepare_survives_reconfig_via_heartbeat_failover"; + + testPrepareFailoverDueToReconfig(testName, /* reconfigOnPrimary */ false); +})(); |