Skip to content

Commit b26c328

Browse files
fix(NODE-5720): on pre-4.4 sharded servers, the node driver uses error.writeConcern.code to determine retryability (#4155)
1 parent e902584 commit b26c328

File tree

4 files changed

+17
-9
lines changed

4 files changed

+17
-9
lines changed

src/cmap/connect.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ export async function performInitialHandshake(
164164
} catch (error) {
165165
if (error instanceof MongoError) {
166166
error.addErrorLabel(MongoErrorLabel.HandshakeError);
167-
if (needsRetryableWriteLabel(error, response.maxWireVersion)) {
167+
if (needsRetryableWriteLabel(error, response.maxWireVersion, conn.description.type)) {
168168
error.addErrorLabel(MongoErrorLabel.RetryableWriteError);
169169
}
170170
}

src/error.ts

+15-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { Document } from './bson';
2+
import type { ServerType } from './sdam/common';
23
import type { TopologyVersion } from './sdam/server_description';
34
import type { TopologyDescription } from './sdam/topology_description';
45

@@ -1226,7 +1227,11 @@ const RETRYABLE_READ_ERROR_CODES = new Set<number>([
12261227
// see: https://github.com/mongodb/specifications/blob/master/source/retryable-writes/retryable-writes.rst#terms
12271228
const RETRYABLE_WRITE_ERROR_CODES = RETRYABLE_READ_ERROR_CODES;
12281229

1229-
export function needsRetryableWriteLabel(error: Error, maxWireVersion: number): boolean {
1230+
export function needsRetryableWriteLabel(
1231+
error: Error,
1232+
maxWireVersion: number,
1233+
serverType: ServerType
1234+
): boolean {
12301235
// pre-4.4 server, then the driver adds an error label for every valid case
12311236
// execute operation will only inspect the label, code/message logic is handled here
12321237
if (error instanceof MongoNetworkError) {
@@ -1246,11 +1251,17 @@ export function needsRetryableWriteLabel(error: Error, maxWireVersion: number):
12461251
}
12471252

12481253
if (error instanceof MongoWriteConcernError) {
1249-
return RETRYABLE_WRITE_ERROR_CODES.has(error.result.writeConcernError.code ?? error?.code ?? 0);
1254+
if (serverType === 'Mongos' && maxWireVersion < 9) {
1255+
// use original top-level code from server response
1256+
return RETRYABLE_WRITE_ERROR_CODES.has(error.result.code ?? 0);
1257+
}
1258+
return RETRYABLE_WRITE_ERROR_CODES.has(
1259+
error.result.writeConcernError.code ?? Number(error.code) ?? 0
1260+
);
12501261
}
12511262

1252-
if (error instanceof MongoError && typeof error.code === 'number') {
1253-
return RETRYABLE_WRITE_ERROR_CODES.has(error.code);
1263+
if (error instanceof MongoError) {
1264+
return RETRYABLE_WRITE_ERROR_CODES.has(Number(error.code));
12541265
}
12551266

12561267
const isNotWritablePrimaryError = LEGACY_NOT_WRITABLE_PRIMARY_ERROR_MESSAGE.test(error.message);

src/sdam/server.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,7 @@ export class Server extends TypedEventEmitter<ServerEvents> {
453453
} else {
454454
if (
455455
(isRetryableWritesEnabled(this.topology) || isTransactionCommand(cmd)) &&
456-
needsRetryableWriteLabel(error, maxWireVersion(this)) &&
456+
needsRetryableWriteLabel(error, maxWireVersion(this), this.description.type) &&
457457
!inActiveTransaction(session, cmd)
458458
) {
459459
error.addErrorLabel(MongoErrorLabel.RetryableWriteError);

test/integration/retryable-writes/retryable_writes.spec.test.ts

-3
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,6 @@ describe('Retryable Writes (unified)', function () {
1919
runUnifiedSuite(loadSpecTests(path.join('retryable-writes', 'unified')), ({ description }) => {
2020
return clientBulkWriteTests.includes(description)
2121
? `TODO(NODE-6257): implement client-level bulk write.`
22-
: description ===
23-
'RetryableWriteError label is not added based on writeConcernError in pre-4.4 mongos response'
24-
? 'TODO(NODE-5720)'
2522
: false;
2623
});
2724
});

0 commit comments

Comments
 (0)