summaryrefslogtreecommitdiff
path: root/src/mongo/s/async_requests_sender.cpp
diff options
context:
space:
mode:
authorLucas de Castro Borges <lucas@gnuabordo.com.br>2025-02-14 14:26:38 -0300
committerLucas de Castro Borges <lucas@gnuabordo.com.br>2025-02-14 14:26:38 -0300
commit294bc6ecabf14c09c9bc8644704921dcf97cb44e (patch)
tree279b1e0bab53901a1647ac63c1c724f0f789a663 /src/mongo/s/async_requests_sender.cpp
parent70be7c27a251621187a1de533462ae2bb1e3bd39 (diff)
parent1e917fd798aa25b7066d4b414b51184f13d5a092 (diff)
Update upstream source from tag 'upstream/6.0.10'debian/6.0.10-1
Update to upstream version '6.0.10' with Debian dir 2d176fa254eee97b139f712fec5709641335a8c3
Diffstat (limited to 'src/mongo/s/async_requests_sender.cpp')
-rw-r--r--src/mongo/s/async_requests_sender.cpp113
1 files changed, 64 insertions, 49 deletions
diff --git a/src/mongo/s/async_requests_sender.cpp b/src/mongo/s/async_requests_sender.cpp
index 1fceefc428e..a5100472f69 100644
--- a/src/mongo/s/async_requests_sender.cpp
+++ b/src/mongo/s/async_requests_sender.cpp
@@ -37,6 +37,7 @@
#include <memory>
#include "mongo/client/remote_command_targeter.h"
+#include "mongo/db/curop.h"
#include "mongo/executor/remote_command_request.h"
#include "mongo/logv2/log.h"
#include "mongo/rpc/get_status_from_command_result.h"
@@ -87,6 +88,8 @@ AsyncRequestsSender::AsyncRequestsSender(OperationContext* opCtx,
// Kick off requests immediately.
_remotes.emplace_back(this, request.shardId, request.cmdObj).executeRequest();
}
+
+ CurOp::get(_opCtx)->ensureRecordRemoteOpWait();
}
AsyncRequestsSender::Response AsyncRequestsSender::next() noexcept {
@@ -117,9 +120,22 @@ AsyncRequestsSender::Response AsyncRequestsSender::next() noexcept {
_resourceYielder->yield(_opCtx);
}
+ auto curOp = CurOp::get(_opCtx);
+ // Calculating the total wait time for remote operations relies on the CurOp's timing
+ // measurement facility and we can't use such facility when the current operation is marked
+ // as done. Some commands such as 'analyzeShardKey' command may send remote operations using
+ // AsyncRequestsSender even after marking the current operation done and so we need to check
+ // whether the current operation is still in progress.
+ auto curOpInProgress = !curOp->isDone();
+ if (curOpInProgress) {
+ curOp->startRemoteOpWaitTimer();
+ }
// Only wait for the next result without popping it, so an error unyielding doesn't
// discard an already popped response.
auto waitStatus = _responseQueue.waitForNonEmptyNoThrow(_opCtx);
+ if (curOpInProgress) {
+ curOp->stopRemoteOpWaitTimer();
+ }
auto unyieldStatus =
_resourceYielder ? _resourceYielder->unyieldNoThrow(_opCtx) : Status::OK();
@@ -170,9 +186,10 @@ AsyncRequestsSender::RemoteData::RemoteData(AsyncRequestsSender* ars,
BSONObj cmdObj)
: _ars(ars), _shardId(std::move(shardId)), _cmdObj(std::move(cmdObj)) {}
-std::shared_ptr<Shard> AsyncRequestsSender::RemoteData::getShard() {
- // TODO: Pass down an OperationContext* to use here.
- return Grid::get(getGlobalServiceContext())->shardRegistry()->getShardNoReload(_shardId);
+SemiFuture<std::shared_ptr<Shard>> AsyncRequestsSender::RemoteData::getShard() noexcept {
+ return Grid::get(getGlobalServiceContext())
+ ->shardRegistry()
+ ->getShard(*_ars->_subBaton, _shardId);
}
void AsyncRequestsSender::RemoteData::executeRequest() {
@@ -192,7 +209,12 @@ void AsyncRequestsSender::RemoteData::executeRequest() {
auto AsyncRequestsSender::RemoteData::scheduleRequest()
-> SemiFuture<RemoteCommandOnAnyCallbackArgs> {
- return resolveShardIdToHostAndPorts(_ars->_readPreference)
+ return getShard()
+ .thenRunOn(*_ars->_subBaton)
+ .then([this](auto&& shard) {
+ return shard->getTargeter()->findHosts(_ars->_readPreference,
+ CancellationToken::uncancelable());
+ })
.thenRunOn(*_ars->_subBaton)
.then([this](auto&& hostAndPorts) {
_shardHostAndPort.emplace(hostAndPorts.front());
@@ -202,17 +224,6 @@ auto AsyncRequestsSender::RemoteData::scheduleRequest()
.semi();
}
-SemiFuture<std::vector<HostAndPort>> AsyncRequestsSender::RemoteData::resolveShardIdToHostAndPorts(
- const ReadPreferenceSetting& readPref) {
- const auto shard = getShard();
- if (!shard) {
- return Status(ErrorCodes::ShardNotFound,
- str::stream() << "Could not find shard " << _shardId);
- }
-
- return shard->getTargeter()->findHosts(readPref, CancellationToken::uncancelable());
-}
-
auto AsyncRequestsSender::RemoteData::scheduleRemoteCommand(std::vector<HostAndPort>&& hostAndPorts)
-> SemiFuture<RemoteCommandOnAnyCallbackArgs> {
hangBeforeSchedulingRemoteCommand.executeIf(
@@ -278,43 +289,47 @@ auto AsyncRequestsSender::RemoteData::handleResponse(RemoteCommandOnAnyCallbackA
}
// There was an error with either the response or the command.
- auto shard = getShard();
- if (!shard) {
- uasserted(ErrorCodes::ShardNotFound, str::stream() << "Could not find shard " << _shardId);
- } else {
- std::vector<HostAndPort> failedTargets;
-
- if (rcr.response.target) {
- failedTargets = {*rcr.response.target};
- } else {
- failedTargets = rcr.request.target;
- }
+ return getShard()
+ .thenRunOn(*_ars->_subBaton)
+ .then([this, status = std::move(status), rcr = std::move(rcr)](
+ std::shared_ptr<mongo::Shard>&& shard) {
+ std::vector<HostAndPort> failedTargets;
- shard->updateReplSetMonitor(failedTargets.front(), status);
- bool isStartingTransaction = _cmdObj.getField("startTransaction").booleanSafe();
- if (!_ars->_stopRetrying && shard->isRetriableError(status.code(), _ars->_retryPolicy) &&
- _retryCount < kMaxNumFailedHostRetryAttempts && !isStartingTransaction) {
-
- LOGV2_DEBUG(4615637,
- 1,
- "Command to remote {shardId} for hosts {hosts} failed with retryable error "
- "{error} and will be retried",
- "Command to remote shard failed with retryable error and will be retried",
- "shardId"_attr = _shardId,
- "hosts"_attr = failedTargets,
- "error"_attr = redact(status));
- ++_retryCount;
- _shardHostAndPort.reset();
- // retry through recursion
- return scheduleRequest();
- }
- }
+ if (rcr.response.target) {
+ failedTargets = {*rcr.response.target};
+ } else {
+ failedTargets = rcr.request.target;
+ }
- // Status' in the response.status field that aren't retried get converted to top level errors
- uassertStatusOK(rcr.response.status);
+ shard->updateReplSetMonitor(failedTargets.front(), status);
+ bool isStartingTransaction = _cmdObj.getField("startTransaction").booleanSafe();
+ if (!_ars->_stopRetrying &&
+ shard->isRetriableError(status.code(), _ars->_retryPolicy) &&
+ _retryCount < kMaxNumFailedHostRetryAttempts && !isStartingTransaction) {
+
+ LOGV2_DEBUG(
+ 4615637,
+ 1,
+ "Command to remote {shardId} for hosts {hosts} failed with retryable error "
+ "{error} and will be retried",
+ "Command to remote shard failed with retryable error and will be retried",
+ "shardId"_attr = _shardId,
+ "hosts"_attr = failedTargets,
+ "error"_attr = redact(status));
+ ++_retryCount;
+ _shardHostAndPort.reset();
+ // retry through recursion
+ return scheduleRequest();
+ }
+
+ // Status' in the response.status field that aren't retried get converted to top level
+ // errors
+ uassertStatusOK(rcr.response.status);
- // We're not okay (on the remote), but still not going to retry
- return std::move(rcr);
+ // We're not okay (on the remote), but still not going to retry
+ return Future<RemoteCommandOnAnyCallbackArgs>::makeReady(std::move(rcr)).semi();
+ })
+ .semi();
};
} // namespace mongo