/** * Test to make sure that if there are uncommitted transactions right when the resharding command * begins, it will select a cloneTimestamp that is greater than the operation time of those * transactions when they commit. * * @tags: [uses_atclustertime] */ (function() { "use strict"; load("jstests/sharding/libs/resharding_test_fixture.js"); const reshardingTest = new ReshardingTest({numDonors: 2, numRecipients: 2, reshardInPlace: true}); reshardingTest.setup(); const donorShardNames = reshardingTest.donorShardNames; const sourceCollection = reshardingTest.createShardedCollection({ ns: "reshardingDb.coll", shardKeyPattern: {oldKey: 1}, chunks: [ {min: {oldKey: MinKey}, max: {oldKey: 10}, shard: donorShardNames[0]}, {min: {oldKey: 10}, max: {oldKey: MaxKey}, shard: donorShardNames[1]}, ], }); const mongos = sourceCollection.getMongo(); const session = mongos.startSession({causalConsistency: false, retryWrites: false}); const sessionCollection = session.getDatabase(sourceCollection.getDB().getName()) .getCollection(sourceCollection.getName()); assert.commandWorked(sessionCollection.insert({_id: 0, oldKey: 5, newKey: 15, counter: 0})); session.startTransaction(); assert.commandWorked(sessionCollection.update({_id: 0, oldKey: 5}, {$inc: {counter: 1}})); const recipientShardNames = reshardingTest.recipientShardNames; reshardingTest.withReshardingInBackground( { newShardKeyPattern: {newKey: 1}, newChunks: [ {min: {newKey: MinKey}, max: {newKey: 10}, shard: recipientShardNames[0]}, {min: {newKey: 10}, max: {newKey: MaxKey}, shard: recipientShardNames[1]}, ], }, () => { // Make sure that the resharding donor service will be blocked waiting for the MODE_S lock // for the collection being resharded because of a transaction that started prior to the // resharding command. Once we confirmed this, we can let the transaction commit and allow // the resharding command to complete. assert.soon(() => { let curOpOpt = {idleSessions: false, allUsers: true, idleConnections: true}; let matchStage = {$match: {'locks.Collection': 'R', desc: /ReshardingDonorService/}}; let curOpResults = mongos.getDB('admin').aggregate([{$currentOp: curOpOpt}, matchStage]).toArray(); return curOpResults.length > 0; }); let coordinatorDoc = mongos.getCollection("config.reshardingOperations").findOne({ ns: sourceCollection.getFullName() }); assert.neq(null, coordinatorDoc); assert.eq(undefined, coordinatorDoc.cloneTimestamp); let res = assert.commandWorked(session.commitTransaction_forTesting()); let commitOperationTS = res.operationTime; assert.soon(() => { coordinatorDoc = mongos.getCollection("config.reshardingOperations").findOne({ ns: sourceCollection.getFullName() }); return coordinatorDoc !== null && coordinatorDoc.cloneTimestamp !== undefined; }); assert.eq(1, timestampCmp(coordinatorDoc.cloneTimestamp, commitOperationTS), 'coordinatorDoc: ' + tojson(coordinatorDoc) + ', commit opTs: ' + tojson(commitOperationTS)); }); reshardingTest.teardown(); })();