diff --git a/jstests/noPassthrough/admission/ingress_request_rate_limiter.js b/jstests/noPassthrough/admission/ingress_request_rate_limiter.js index 86bb28cd4ca..85610c72c18 100644 --- a/jstests/noPassthrough/admission/ingress_request_rate_limiter.js +++ b/jstests/noPassthrough/admission/ingress_request_rate_limiter.js @@ -20,6 +20,8 @@ import { runTestStandalone, } from "jstests/noPassthrough/admission/libs/ingress_request_rate_limiter_helper.js"; +const kExpectedErrorLabels = ["SystemOverloadedError", "RetryableError", "NoWritesPerformed"]; + /** * Runs the set parameter commands with some arbitrary value to ensure invalid values are rejected. */ @@ -114,7 +116,7 @@ function testRateLimiterMetrics(conn, exemptConn) { for (let i = 0; i < requestAmount; ++i) { const assertContainsExpectedErrorLabels = (res) => { assert(res.hasOwnProperty("errorLabels"), res); - assert.sameMembers(["SystemOverloadedError", "RetryableError"], res.errorLabels); + assert.sameMembers(kExpectedErrorLabels, res.errorLabels); }; const collName = `${jsTest.name()}_coll`; @@ -282,7 +284,7 @@ function runTestCompressed() { const compressionArgs = ["--networkMessageCompressors", kCompressor]; const shell = startParallelShell( funWithArgs( - (host, params, exemptAppName, requestAmount) => { + (host, params, exemptAppName, requestAmount, expectedLabels) => { const exemptConn = new Mongo(`mongodb://${host}/?appName=${exemptAppName}`); exemptConn.getDB("admin").auth("admin", "pwd"); assert.commandWorked( @@ -293,8 +295,7 @@ function runTestCompressed() { for (let i = 0; i < requestAmount; ++i) { const assertContainSystemOverloadedErrorLabel = (res) => { assert(res.hasOwnProperty("errorLabels"), res); - assert.sameMembers(["SystemOverloadedError", "RetryableError"], - res.errorLabels); + assert.sameMembers(expectedLabels, res.errorLabels); }; const collName = `${jsTest.name()}_coll`; @@ -313,7 +314,9 @@ function runTestCompressed() { mongod.host, JSON.stringify(kParams), kRateLimiterExemptAppName, - requestAmount), + requestAmount, + kExpectedErrorLabels, + ), mongod.port, false, ...compressionArgs); diff --git a/src/mongo/db/error_labels.cpp b/src/mongo/db/error_labels.cpp index fcfab5385de..74b2026227a 100644 --- a/src/mongo/db/error_labels.cpp +++ b/src/mongo/db/error_labels.cpp @@ -215,6 +215,7 @@ void ErrorLabelBuilder::build(BSONArrayBuilder& labels) const { labels << ErrorLabel::kNoWritesPerformed; } } else if (isOperationIdempotent()) { + // TODO SERVER-108898: apply the NoWritesPerformed error label here too, if appropriate. labels << ErrorLabel::kRetryableError; } } diff --git a/src/mongo/transport/session_workflow.cpp b/src/mongo/transport/session_workflow.cpp index 3607660d603..ea76a31fcc4 100644 --- a/src/mongo/transport/session_workflow.cpp +++ b/src/mongo/transport/session_workflow.cpp @@ -744,6 +744,9 @@ DbResponse makeDbResponseErrorForRateLimiting(const Message& message, const Stat BSONArrayBuilder arrayBuilder(commandBodyBob.subarrayStart(kErrorLabelsFieldName)); arrayBuilder.append(ErrorLabel::kSystemOverloadedError); arrayBuilder.append(ErrorLabel::kRetryableError); + // It can't be determined whether the request being rejected is a write or not without + // deserializing it, so we just always append the NoWritesPerformed label. + arrayBuilder.append(ErrorLabel::kNoWritesPerformed); } }