From 3cbcc55f33eb79b3f44c7d3bb09c10c2da450a6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pol=20Pi=C3=B1ol=20Castuera?= Date: Mon, 20 Apr 2026 16:24:26 +0200 Subject: [PATCH] SERVER-124506 Make CollectionCacheRecoverer use makeNewAllowingGaps when reading from shard catalog disk (#52133) GitOrigin-RevId: cb108aaafb21252788df0a37b46c61b40cea4700 --- .../collection_cache_recoverer.cpp | 24 +++++----- .../shard_filtering_metadata_refresh_test.cpp | 48 +++++++++++++++++++ 2 files changed, 60 insertions(+), 12 deletions(-) diff --git a/src/mongo/db/shard_role/shard_catalog/collection_cache_recoverer.cpp b/src/mongo/db/shard_role/shard_catalog/collection_cache_recoverer.cpp index 86604eb3c23..fb50027c4a6 100644 --- a/src/mongo/db/shard_role/shard_catalog/collection_cache_recoverer.cpp +++ b/src/mongo/db/shard_role/shard_catalog/collection_cache_recoverer.cpp @@ -101,18 +101,18 @@ CollectionMetadata recoverCollectionFromDisk(OperationContext* opCtx, return nullptr; }(); auto rt = OptionalRoutingTableHistory{std::make_shared( - RoutingTableHistory::makeNew(coll->getNss(), - coll->getUuid(), - coll->getKeyPattern(), - coll->getUnsplittable(), - std::move(defaultCollator), - coll->getUnique(), - coll->getEpoch(), - coll->getTimestamp(), - coll->getTimeseriesFields(), - coll->getReshardingFields(), - coll->getAllowMigrations(), - chunks))}; + RoutingTableHistory::makeNewAllowingGaps(coll->getNss(), + coll->getUuid(), + coll->getKeyPattern(), + coll->getUnsplittable(), + std::move(defaultCollator), + coll->getUnique(), + coll->getEpoch(), + coll->getTimestamp(), + coll->getTimeseriesFields(), + coll->getReshardingFields(), + coll->getAllowMigrations(), + chunks))}; auto cm = CurrentChunkManager{std::move(rt)}; return CollectionMetadata{std::move(cm), ShardingState::get(opCtx)->shardId()}; } diff --git a/src/mongo/db/shard_role/shard_catalog/shard_filtering_metadata_refresh_test.cpp b/src/mongo/db/shard_role/shard_catalog/shard_filtering_metadata_refresh_test.cpp index 6380c7ff537..eb550c21cdb 100644 --- a/src/mongo/db/shard_role/shard_catalog/shard_filtering_metadata_refresh_test.cpp +++ b/src/mongo/db/shard_role/shard_catalog/shard_filtering_metadata_refresh_test.cpp @@ -667,6 +667,54 @@ TEST_F(AuthoritativeRefreshFixture, ASSERT_FALSE(metadataOpt->getShardPlacementVersion().isSet()); } +TEST_F(AuthoritativeRefreshFixture, PartialRangeDiskCatalogRecoversWithoutChunkMetadata) { + RAIIServerParameterControllerForTest featureFlag("featureFlagShardAuthoritativeCollMetadata", + true); + auto* opCtx = operationContext(); + + const UUID uuid = UUID::gen(); + const OID epoch = OID::gen(); + const Timestamp timestamp(Date_t::now()); + + CollectionType collType{kTestNss, epoch, timestamp, Date_t::now(), uuid, kShardKeyPattern}; + + // Build two contiguous chunks owned by this shard whose extremes are neither MinKey nor + // MaxKey. The "missing" chunks [MinKey, 100) and [300, MaxKey] logically exist on + // "otherShard" but are not persisted on this node, exactly as `fetchOwnedChunks` would + // produce at runtime. + auto makeChunk = [&](BSONObj min, BSONObj max, ChunkVersion v) { + ChunkType c{uuid, ChunkRange(std::move(min), std::move(max)), v, kMyShardName}; + c.setName(OID::gen()); + return c; + }; + + ChunkVersion v({epoch, timestamp}, {1, 0}); + std::vector myOwnedChunks; + myOwnedChunks.push_back(makeChunk(BSON(kShardKey << 100), BSON(kShardKey << 200), v)); + v.incMajor(); + myOwnedChunks.push_back(makeChunk(BSON(kShardKey << 200), BSON(kShardKey << 300), v)); + + populateDiskCatalog(opCtx, collType, myOwnedChunks); + + { + auto csr = CollectionShardingRuntime::acquireExclusive(opCtx, kTestNss); + csr->clearFilteringMetadata_authoritative(opCtx); + } + + auto status = onShardVersionMismatch(opCtx, kTestNss, boost::none); + ASSERT_OK(status); + + auto csr = CollectionShardingRuntime::acquireShared(opCtx, kTestNss); + auto metadataOpt = csr->getCurrentMetadataIfKnown(); + ASSERT_TRUE(metadataOpt.has_value()); + ASSERT_TRUE(metadataOpt->isSharded()); + ASSERT_TRUE(metadataOpt->getShardPlacementVersion().isSet()); + ASSERT_EQ(metadataOpt->getShardPlacementVersion(), myOwnedChunks.back().getVersion()); + auto stats = getStatistics(opCtx); + ASSERT_EQ(stats.getIntField("diskRecoveriesPerformed"), 1); + ASSERT_EQ(stats.getIntField("recoverersCreated"), 1); +} + TEST_F(AuthoritativeRefreshFixture, SequentialCallsAreIdempotent) { RAIIServerParameterControllerForTest featureFlag("featureFlagShardAuthoritativeCollMetadata", true);