diff --git a/jstests/sharding/drop_database_before_write_is_targeted.js b/jstests/sharding/drop_database_before_write_is_targeted.js index c1e86679fe6..350bd9bd88b 100644 --- a/jstests/sharding/drop_database_before_write_is_targeted.js +++ b/jstests/sharding/drop_database_before_write_is_targeted.js @@ -22,12 +22,24 @@ const st = new ShardingTest({mongos: 1, shards: 1, config: 1}); let failPoint = configureFailPoint(st.s, 'waitForDatabaseToBeDropped'); let insertThread = new Thread((mongosConnString, collNS) => { + Random.setRandomSeed() + let mongos = new Mongo(mongosConnString); - assert.commandWorked(mongos.getCollection(collNS).insert({})); + try { + let bulk = mongos.getCollection(collNS).initializeUnorderedBulkOp(); + for (let i = 0; i < 100; ++i) { + bulk.insert({key: Random.randInt(10000)}); + } + assert.commandWorked(bulk.execute()); + } catch (ex) { + assert.eq(true, ex instanceof BulkWriteError, tojson(ex)); + assert.writeErrorWithCode(ex, ErrorCodes.DatabaseDropPending); + } }, st.s0.host, collNS); // Perform a write operation, the database is implicitly created then the operation is paused. insertThread.start(); +sleep(100); failPoint.wait(); // Before the router targets the write operation, the database is dropped. diff --git a/src/mongo/s/collection_routing_info_targeter.cpp b/src/mongo/s/collection_routing_info_targeter.cpp index 89f9253f56b..50ed5d77542 100644 --- a/src/mongo/s/collection_routing_info_targeter.cpp +++ b/src/mongo/s/collection_routing_info_targeter.cpp @@ -251,29 +251,32 @@ CollectionRoutingInfoTargeter::CollectionRoutingInfoTargeter(const NamespaceStri * namespace. */ CollectionRoutingInfo CollectionRoutingInfoTargeter::_init(OperationContext* opCtx, bool refresh) { - auto [cm, sii] = [&] { + auto createDatabaseAndGetRoutingInfo = [&](auto& nss) { size_t attempts = 1; while (true) { try { - cluster::createDatabase(opCtx, _nss.dbName()); + cluster::createDatabase(opCtx, nss.dbName()); if (refresh) { uassertStatusOK( - Grid::get(opCtx)->catalogCache()->getCollectionRoutingInfoWithRefresh( - opCtx, _nss)); + Grid::get(opCtx)->catalogCache()->getCollectionRoutingInfoWithRefresh(opCtx, + nss)); } + logd("DEBUG-1 --pre-- ns={}", nss); if (MONGO_unlikely(waitForDatabaseToBeDropped.shouldFail())) { + logd("DEBUG-1 --in-- ns={}", nss); LOGV2(8314600, "Hanging due to waitForDatabaseToBeDropped fail point"); waitForDatabaseToBeDropped.pauseWhileSet(opCtx); } + logd("DEBUG-1 --after-- ns={}", nss); - return uassertStatusOK(getCollectionRoutingInfoForTxnCmd(opCtx, _nss)); + return uassertStatusOK(getCollectionRoutingInfoForTxnCmd(opCtx, nss)); } catch (const ExceptionFor&) { LOGV2_INFO(8314601, "Failed initialization of routing info because the database has been " "concurrently dropped", - logAttrs(_nss.dbName()), + logAttrs(nss.dbName()), "attemptNumber"_attr = attempts, "maxAttempts"_attr = kMaxDatabaseCreationAttempts); @@ -285,7 +288,9 @@ CollectionRoutingInfo CollectionRoutingInfoTargeter::_init(OperationContext* opC } } } - }(); + }; + + auto [cm, sii] = createDatabaseAndGetRoutingInfo(_nss); // For a tracked time-series collection, only the underlying buckets collection is stored on the // config servers. If the user operation is on the time-series view namespace, we should check @@ -302,12 +307,8 @@ CollectionRoutingInfo CollectionRoutingInfoTargeter::_init(OperationContext* opC // back to the view namespace and reset '_isRequestOnTimeseriesViewNamespace'. if (!cm.hasRoutingTable() && !_nss.isTimeseriesBucketsCollection()) { auto bucketsNs = _nss.makeTimeseriesBucketsNamespace(); - if (refresh) { - uassertStatusOK(Grid::get(opCtx)->catalogCache()->getCollectionRoutingInfoWithRefresh( - opCtx, bucketsNs)); - } - auto [bucketsPlacementInfo, bucketsIndexInfo] = - uassertStatusOK(getCollectionRoutingInfoForTxnCmd(opCtx, bucketsNs)); + auto [bucketsPlacementInfo, bucketsIndexInfo] = createDatabaseAndGetRoutingInfo(bucketsNs); + if (bucketsPlacementInfo.hasRoutingTable()) { _nss = bucketsNs; cm = std::move(bucketsPlacementInfo); @@ -318,12 +319,8 @@ CollectionRoutingInfo CollectionRoutingInfoTargeter::_init(OperationContext* opC // This can happen if a tracked time-series collection is dropped and re-created. Then we // need to reset the namespace to the original namespace. _nss = _nss.getTimeseriesViewNamespace(); + auto [newCm, newSii] = createDatabaseAndGetRoutingInfo(_nss); - if (refresh) { - uassertStatusOK( - Grid::get(opCtx)->catalogCache()->getCollectionRoutingInfoWithRefresh(opCtx, _nss)); - } - auto [newCm, newSii] = uassertStatusOK(getCollectionRoutingInfoForTxnCmd(opCtx, _nss)); cm = std::move(newCm); sii = std::move(newSii); _isRequestOnTimeseriesViewNamespace = false;