/** * Tests the idempotency of the _configsvrCommitRefineCollectionShardKey command. * * @tags: [ * does_not_support_stepdowns, * ] */ import {ShardingTest} from "jstests/libs/shardingtest.js"; (function () { "use strict"; function runConfigsvrCommitRefineCollectionShardKey(st, ns, oldTimestamp, newTimestamp, newKey) { return st.configRS.getPrimary().adminCommand({ _configsvrCommitRefineCollectionShardKey: ns, key: newKey, newTimestamp: newTimestamp, newEpoch: new ObjectId(), oldTimestamp: oldTimestamp, writeConcern: {w: "majority"}, }); } const st = new ShardingTest({shards: 1}); const dbName = "test"; const collName = "foo"; const ns = dbName + "." + collName; const initialShardKey = { x: 1, }; const newShardKey = { x: 1, y: 1, }; assert.commandWorked(st.s.adminCommand({shardCollection: ns, key: initialShardKey})); const initialCollectionMetadata = st.s.getCollection("config.collections").findOne({_id: ns}); assert.eq(initialShardKey, initialCollectionMetadata.key); assert.commandWorked( st.s.getDB(dbName).runCommand({createIndexes: collName, indexes: [{key: newShardKey, name: "index_2"}]}), ); // First run of the command, should succeed, check that the metadata changed. assert.commandWorked( runConfigsvrCommitRefineCollectionShardKey( st, ns, initialCollectionMetadata.timestamp, Timestamp(), newShardKey, ), ); const finalCollectionMetadata = st.s.getCollection("config.collections").findOne({_id: ns}); assert.neq(initialCollectionMetadata.key, finalCollectionMetadata.key); assert.neq(initialCollectionMetadata.timestamp, finalCollectionMetadata.timestamp); assert.neq(initialCollectionMetadata.lastmodEpoch, finalCollectionMetadata.lastmodEpoch); // Idempotency check, the command should succeed but no change should happen. assert.commandWorked( runConfigsvrCommitRefineCollectionShardKey( st, ns, initialCollectionMetadata.timestamp, finalCollectionMetadata.timestamp, newShardKey, ), ); // Ensure causality by making sure all nodes have the commit replicated. st.configRS.awaitLastOpCommitted(1 * 60 * 1000); const noopCollectionMetadata = st.s.getCollection("config.collections").findOne({_id: ns}); assert.eq(noopCollectionMetadata.key, finalCollectionMetadata.key); assert.eq(noopCollectionMetadata.timestamp, finalCollectionMetadata.timestamp); assert.eq(noopCollectionMetadata.lastmodEpoch, finalCollectionMetadata.lastmodEpoch); // This should fail, the newTimestamp must match with the first newTimestamp committed, just like // the oldTimestamp does. assert.commandFailedWithCode( runConfigsvrCommitRefineCollectionShardKey( st, ns, initialCollectionMetadata.timestamp, Timestamp(), newShardKey, ), 7648608, ); // This should also fail, oldTimestamp will not match. assert.commandFailedWithCode( runConfigsvrCommitRefineCollectionShardKey(st, ns, Timestamp(), Timestamp(), newShardKey), 7648608, ); assert.commandWorked(st.shard0.adminCommand({_flushRoutingTableCacheUpdates: ns})); st.stop(); })();