Skip to content
This repository was archived by the owner on Oct 31, 2023. It is now read-only.

Commit 1e10e32

Browse files
BillyDonahueEvergreen Agent
authored andcommitted
SERVER-50549 transform state-changing errors returned by mongos
1 parent e8bfaf0 commit 1e10e32

18 files changed

+621
-12
lines changed

jstests/sharding/change_stream_error_label.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ const expectedStopShardErrors = [
4242
// First, verify that the 'failGetMoreAfterCursorCheckout' failpoint can effectively exercise the
4343
// error label generation logic for change stream getMores.
4444
function testFailGetMoreAfterCursorCheckoutFailpoint({errorCode, expectedLabel}) {
45+
errorCode = ErrorCodes.doMongosRewrite(errorCode);
4546
// Activate the failpoint and set the exception that it will throw.
4647
assert.commandWorked(testDB.adminCommand({
4748
configureFailPoint: "failGetMoreAfterCursorCheckout",

jstests/sharding/linearizable_read_concern.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ var res = assert.commandFailed(testDB.runReadCommand({
8585
readConcern: {level: "linearizable"},
8686
maxTimeMS: shard0ReplTest.kDefaultTimeoutMS
8787
}));
88-
assert.eq(res.code, ErrorCodes.NotWritablePrimary);
88+
assert.eq(res.code, ErrorCodes.doMongosRewrite(ErrorCodes.NotWritablePrimary));
8989

9090
jsTestLog("Testing linearizable read from primaries.");
9191

jstests/sharding/mongos_not_retry_commands_in_transactions.js

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,16 @@ jsTest.log(
5454
"Testing that mongos doesn't retry the read command with startTransaction=true on replication set failover.");
5555
assert.commandWorked(setCommandToFail(primaryConnection, "find", kNs));
5656

57-
assert.commandFailedWithCode(mongosDB.runCommand({
58-
find: kCollName,
59-
filter: kDoc0,
60-
startTransaction: true,
61-
txnNumber: NumberLong(transactionNumber++),
62-
stmtId: NumberInt(0),
63-
autocommit: false
64-
}),
65-
ErrorCodes.InterruptedDueToReplStateChange);
57+
assert.commandFailedWithCode(
58+
mongosDB.runCommand({
59+
find: kCollName,
60+
filter: kDoc0,
61+
startTransaction: true,
62+
txnNumber: NumberLong(transactionNumber++),
63+
stmtId: NumberInt(0),
64+
autocommit: false
65+
}),
66+
ErrorCodes.doMongosRewrite(ErrorCodes.InterruptedDueToReplStateChange));
6667

6768
jsTest.log("Testing that mongos retries retryable writes on failover.");
6869
assert.commandWorked(setCommandToFail(primaryConnection, "insert", kNs));

jstests/sharding/retryable_write_error_labels.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ const st = new ShardingTest({
2828
});
2929

3030
function checkErrorCode(res, errorCode, isWCError) {
31+
errorCode = ErrorCodes.doMongosRewrite(errorCode);
3132
if (isWCError) {
3233
assert.neq(null, res.writeConcernError, res);
3334
assert.eq(res.writeConcernError.code, errorCode, res);

jstests/sharding/transactions_writes_not_retryable.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ function runTest(st, session, sessionDB, writeCmdName, writeCmd, isSharded) {
3131
session.startTransaction();
3232
assert.commandFailedWithCode(
3333
sessionDB.runCommand(writeCmd),
34-
retryableError,
34+
ErrorCodes.doMongosRewrite(retryableError),
3535
"expected write in transaction not to be retried on retryable error, cmd: " +
3636
tojson(writeCmd) + ", sharded: " + isSharded);
3737
assert.commandFailedWithCode(session.abortTransaction_forTesting(),

src/mongo/db/SConscript

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,7 @@ env.Library(
601601
'$BUILD_DIR/mongo/db/query/explain_options',
602602
'$BUILD_DIR/mongo/idl/idl_parser',
603603
'$BUILD_DIR/mongo/rpc/command_status',
604+
'$BUILD_DIR/mongo/rpc/rewrite_state_change_errors',
604605
'$BUILD_DIR/mongo/rpc/rpc',
605606
'audit',
606607
'auth/auth',

src/mongo/db/commands.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
#include "mongo/rpc/metadata/client_metadata.h"
6262
#include "mongo/rpc/op_msg_rpc_impls.h"
6363
#include "mongo/rpc/protocol.h"
64+
#include "mongo/rpc/rewrite_state_change_errors.h"
6465
#include "mongo/rpc/write_concern_error_detail.h"
6566
#include "mongo/s/stale_exception.h"
6667
#include "mongo/util/fail_point.h"
@@ -681,6 +682,13 @@ void CommandHelpers::evaluateFailCommandFailPoint(OperationContext* opCtx,
681682
const Command* cmd = invocation->definition();
682683
failCommand.executeIf(
683684
[&](const BSONObj& data) {
685+
// State change codes are rewritten on the way out of a `mongos`
686+
// server. Errors injected via failpoint manipulation are normally
687+
// exempt from this. However, we provide an override option so they
688+
// can be made subject to rewriting if that's really necessary.
689+
if (bool b; !bsonExtractBooleanField(data, "allowRewriteStateChange", &b).isOK() || !b)
690+
rpc::RewriteStateChangeErrors::setEnabled(opCtx, false);
691+
684692
if (data.hasField(kErrorLabelsFieldName) &&
685693
data[kErrorLabelsFieldName].type() == Array) {
686694
// Propagate error labels specified in the failCommand failpoint to the

src/mongo/db/commands/SConscript

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,7 @@ env.Library(
360360
'$BUILD_DIR/mongo/db/views/views_mongod',
361361
'$BUILD_DIR/mongo/executor/async_request_executor',
362362
'$BUILD_DIR/mongo/idl/feature_flag',
363+
'$BUILD_DIR/mongo/rpc/rewrite_state_change_errors',
363364
'$BUILD_DIR/mongo/util/log_and_backoff',
364365
'$BUILD_DIR/mongo/util/net/http_client',
365366
'core',

src/mongo/db/commands/getmore_cmd.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include <memory>
3737
#include <string>
3838

39+
#include "mongo/bson/util/bson_extract.h"
3940
#include "mongo/db/api_parameters.h"
4041
#include "mongo/db/auth/authorization_checks.h"
4142
#include "mongo/db/auth/authorization_session.h"
@@ -64,6 +65,7 @@
6465
#include "mongo/db/stats/resource_consumption_metrics.h"
6566
#include "mongo/db/stats/top.h"
6667
#include "mongo/logv2/log.h"
68+
#include "mongo/rpc/rewrite_state_change_errors.h"
6769
#include "mongo/s/chunk_version.h"
6870
#include "mongo/util/fail_point.h"
6971
#include "mongo/util/scopeguard.h"
@@ -575,7 +577,11 @@ class GetMoreCmd final : public Command {
575577
// If the 'failGetMoreAfterCursorCheckout' failpoint is enabled, throw an exception with
576578
// the given 'errorCode' value, or ErrorCodes::InternalError if 'errorCode' is omitted.
577579
failGetMoreAfterCursorCheckout.executeIf(
578-
[](const BSONObj& data) {
580+
[&](const BSONObj& data) {
581+
if (bool b;
582+
!bsonExtractBooleanField(data, "allowRewriteStateChange", &b).isOK() || !b)
583+
rpc::RewriteStateChangeErrors::setEnabled(opCtx, false);
584+
579585
auto errorCode = (data["errorCode"] ? data["errorCode"].safeNumberLong()
580586
: ErrorCodes::InternalError);
581587
uasserted(errorCode, "Hit the 'failGetMoreAfterCursorCheckout' failpoint");

src/mongo/rpc/SConscript

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,23 @@ env.Library(
7474
],
7575
LIBDEPS_PRIVATE=[
7676
'$BUILD_DIR/mongo/idl/server_parameter',
77+
'rewrite_state_change_errors',
78+
],
79+
)
80+
81+
env.Library(
82+
target='rewrite_state_change_errors',
83+
source=[
84+
'rewrite_state_change_errors.cpp',
85+
'rewrite_state_change_errors_server_parameter.idl',
86+
],
87+
LIBDEPS_PRIVATE=[
88+
'$BUILD_DIR/mongo/base',
89+
'$BUILD_DIR/mongo/bson/mutable/mutable_bson',
90+
'$BUILD_DIR/mongo/db/service_context',
91+
'$BUILD_DIR/mongo/rpc/protocol',
92+
'$BUILD_DIR/mongo/s/is_mongos',
93+
'$BUILD_DIR/third_party/shim_pcrecpp',
7794
],
7895
)
7996

@@ -170,12 +187,14 @@ if wiredtiger:
170187
'op_msg_test.cpp',
171188
'protocol_test.cpp',
172189
'reply_builder_test.cpp',
190+
'rewrite_state_change_errors_test.cpp',
173191
],
174192
LIBDEPS=[
175193
'$BUILD_DIR/mongo/client/clientdriver_minimal',
176194
'$BUILD_DIR/third_party/wiredtiger/wiredtiger_checksum',
177195
'client_metadata',
178196
'metadata',
197+
'rewrite_state_change_errors',
179198
'rpc',
180199
]
181200
)

0 commit comments

Comments
 (0)