Skip to content

Commit 1e5a69c

Browse files
authored
Merge branch 'main' into NODE-6090
2 parents 7baefd1 + b26c328 commit 1e5a69c

26 files changed

+584
-351
lines changed

src/bulk/common.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -617,8 +617,8 @@ function handleMongoWriteConcernError(
617617
callback(
618618
new MongoBulkWriteError(
619619
{
620-
message: err.result?.writeConcernError.errmsg,
621-
code: err.result?.writeConcernError.result
620+
message: err.result.writeConcernError.errmsg,
621+
code: err.result.writeConcernError.code
622622
},
623623
new BulkWriteResult(bulkResult, isOrdered)
624624
)

src/cmap/connect.ts

Lines changed: 1 addition & 1 deletion
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

Lines changed: 34 additions & 14 deletions
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

@@ -1167,6 +1168,23 @@ export class MongoServerSelectionError extends MongoSystemError {
11671168
}
11681169
}
11691170

1171+
/**
1172+
* The type of the result property of MongoWriteConcernError
1173+
* @public
1174+
*/
1175+
export interface WriteConcernErrorResult {
1176+
writeConcernError: {
1177+
code: number;
1178+
errmsg: string;
1179+
codeName?: string;
1180+
errInfo?: Document;
1181+
};
1182+
ok: number;
1183+
code?: number;
1184+
errorLabels?: string[];
1185+
[x: string | number]: unknown;
1186+
}
1187+
11701188
/**
11711189
* An error thrown when the server reports a writeConcernError
11721190
* @public
@@ -1187,16 +1205,8 @@ export class MongoWriteConcernError extends MongoServerError {
11871205
*
11881206
* @public
11891207
**/
1190-
constructor(result: {
1191-
writeConcernError: {
1192-
code: number;
1193-
errmsg: string;
1194-
codeName?: string;
1195-
errInfo?: Document;
1196-
};
1197-
errorLabels?: string[];
1198-
}) {
1199-
super({ ...result, ...result.writeConcernError });
1208+
constructor(result: WriteConcernErrorResult) {
1209+
super({ ...result.writeConcernError, ...result });
12001210
this.errInfo = result.writeConcernError.errInfo;
12011211
this.result = result;
12021212
}
@@ -1226,7 +1236,11 @@ const RETRYABLE_READ_ERROR_CODES = new Set<number>([
12261236
// see: https://github.com/mongodb/specifications/blob/master/source/retryable-writes/retryable-writes.rst#terms
12271237
const RETRYABLE_WRITE_ERROR_CODES = RETRYABLE_READ_ERROR_CODES;
12281238

1229-
export function needsRetryableWriteLabel(error: Error, maxWireVersion: number): boolean {
1239+
export function needsRetryableWriteLabel(
1240+
error: Error,
1241+
maxWireVersion: number,
1242+
serverType: ServerType
1243+
): boolean {
12301244
// pre-4.4 server, then the driver adds an error label for every valid case
12311245
// execute operation will only inspect the label, code/message logic is handled here
12321246
if (error instanceof MongoNetworkError) {
@@ -1246,11 +1260,17 @@ export function needsRetryableWriteLabel(error: Error, maxWireVersion: number):
12461260
}
12471261

12481262
if (error instanceof MongoWriteConcernError) {
1249-
return RETRYABLE_WRITE_ERROR_CODES.has(error.result?.code ?? error.code ?? 0);
1263+
if (serverType === 'Mongos' && maxWireVersion < 9) {
1264+
// use original top-level code from server response
1265+
return RETRYABLE_WRITE_ERROR_CODES.has(error.result.code ?? 0);
1266+
}
1267+
return RETRYABLE_WRITE_ERROR_CODES.has(
1268+
error.result.writeConcernError.code ?? Number(error.code) ?? 0
1269+
);
12501270
}
12511271

1252-
if (error instanceof MongoError && typeof error.code === 'number') {
1253-
return RETRYABLE_WRITE_ERROR_CODES.has(error.code);
1272+
if (error instanceof MongoError) {
1273+
return RETRYABLE_WRITE_ERROR_CODES.has(Number(error.code));
12541274
}
12551275

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

src/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ export {
7474
MongoTopologyClosedError,
7575
MongoTransactionError,
7676
MongoUnexpectedServerResponseError,
77-
MongoWriteConcernError
77+
MongoWriteConcernError,
78+
WriteConcernErrorResult
7879
} from './error';
7980
export {
8081
AbstractCursor,

src/sdam/server.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,7 @@ export class Server extends TypedEventEmitter<ServerEvents> {
460460
} else {
461461
if (
462462
(isRetryableWritesEnabled(this.topology) || isTransactionCommand(cmd)) &&
463-
needsRetryableWriteLabel(error, maxWireVersion(this)) &&
463+
needsRetryableWriteLabel(error, maxWireVersion(this), this.description.type) &&
464464
!inActiveTransaction(session, cmd)
465465
) {
466466
error.addErrorLabel(MongoErrorLabel.RetryableWriteError);

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

Lines changed: 0 additions & 3 deletions
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
});

test/integration/unified-test-format/unified_test_format.spec.test.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,11 @@ const filter: TestFilter = ({ description }) => {
4141
return false;
4242
};
4343

44-
describe('Unified test format runner', function unifiedTestRunner() {
44+
describe('Unified test format runner (valid-pass)', function unifiedTestRunner() {
4545
// Valid tests that should pass
4646
runUnifiedSuite(loadSpecTests('unified-test-format/valid-pass'), filter);
4747
});
48+
49+
describe('Unified test format runner (valid-fail)', function unifiedTestRunner() {
50+
runUnifiedSuite(loadSpecTests('unified-test-format/valid-fail'), () => false, true);
51+
});

0 commit comments

Comments
 (0)