Skip to content

Commit 728ab9e

Browse files
committed
chore: add looping for writeErrors
1 parent d2964ba commit 728ab9e

File tree

3 files changed

+37
-19
lines changed

3 files changed

+37
-19
lines changed

src/cmap/connection.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -621,7 +621,10 @@ export class Connection extends TypedEventEmitter<ConnectionEvents> {
621621
}
622622
} else {
623623
if (
624-
document?.writeErrors?.[0]?.code === MONGODB_ERROR_CODES.MaxTimeMSExpired ||
624+
(Array.isArray(document?.writeErrors) &&
625+
document.writeErrors.some(
626+
error => error?.code === MONGODB_ERROR_CODES.MaxTimeMSExpired
627+
)) ||
625628
document?.writeConcernError?.code === MONGODB_ERROR_CODES.MaxTimeMSExpired
626629
) {
627630
throw new MongoOperationTimeoutError('Server reported a timeout error', {

src/cmap/wire_protocol/responses.ts

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -111,18 +111,31 @@ export class MongoDBResponse extends OnDemandDocument {
111111
* - ok is 1 and the writeConcern object contains a code === 50
112112
*/
113113
get isMaxTimeExpiredError() {
114-
return (
115-
// {ok: 0, code: 50 ... }
116-
(this.ok === 0 && this.code === MONGODB_ERROR_CODES.MaxTimeMSExpired) ||
117-
// {ok: 1, writeErrors: [{code: 50 ... }]}
118-
(this.ok === 1 &&
119-
this.get('writeErrors', BSONType.array)?.get(0, BSONType.object)?.getNumber('code') ===
120-
MONGODB_ERROR_CODES.MaxTimeMSExpired) ||
121-
// {ok: 1, writeConcernError: {code: 50 ... }}
122-
(this.ok === 1 &&
123-
this.get('writeConcernError', BSONType.object)?.getNumber('code') ===
124-
MONGODB_ERROR_CODES.MaxTimeMSExpired)
125-
);
114+
// {ok: 0, code: 50 ... }
115+
const isTopLevel = this.ok === 0 && this.code === MONGODB_ERROR_CODES.MaxTimeMSExpired;
116+
if (isTopLevel) return true;
117+
118+
if (this.ok === 0) return false;
119+
120+
// {ok: 1, writeConcernError: {code: 50 ... }}
121+
const isWriteConcern =
122+
this.get('writeConcernError', BSONType.object)?.getNumber('code') ===
123+
MONGODB_ERROR_CODES.MaxTimeMSExpired;
124+
if (isWriteConcern) return true;
125+
126+
const writeErrors = this.get('writeErrors', BSONType.array);
127+
if (writeErrors?.size()) {
128+
for (let i = 0; i < writeErrors.size(); i++) {
129+
const isWriteError =
130+
writeErrors.get(i, BSONType.object)?.getNumber('code') ===
131+
MONGODB_ERROR_CODES.MaxTimeMSExpired;
132+
133+
// {ok: 1, writeErrors: [{code: 50 ... }]}
134+
if (isWriteError) return true;
135+
}
136+
}
137+
138+
return false;
126139
}
127140

128141
/**

test/integration/client-side-operations-timeout/node_csot.test.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
/* Anything javascript specific relating to timeouts */
22
import { expect } from 'chai';
3-
import * as semver from 'semver';
43
import * as sinon from 'sinon';
54

65
import {
76
BSON,
87
type ClientSession,
8+
Code,
99
type Collection,
1010
Connection,
1111
type Db,
@@ -232,14 +232,16 @@ describe('CSOT driver tests', () => {
232232
});
233233

234234
describe('when a maxTimeExpired error is returned inside a writeErrors array', () => {
235-
// Okay so allegedly this can never happen.
236-
// But the spec says it can, so let's be defensive and support it.
237-
// {ok: 1, writeErrors: [{code: 50, codeName: "MaxTimeMSExpired", errmsg: "operation time limit exceeded"}]}
235+
// The server should always return one maxTimeExpiredError at the front of the writeErrors array
236+
// But for the sake of defensive programming we will find any maxTime error in the array.
238237

239238
beforeEach(async () => {
240239
const writeErrorsReply = BSON.serialize({
241240
ok: 1,
242241
writeErrors: [
242+
{ code: 2, codeName: 'MaxTimeMSExpired', errmsg: 'operation time limit exceeded' },
243+
{ code: 3, codeName: 'MaxTimeMSExpired', errmsg: 'operation time limit exceeded' },
244+
{ code: 4, codeName: 'MaxTimeMSExpired', errmsg: 'operation time limit exceeded' },
243245
{ code: 50, codeName: 'MaxTimeMSExpired', errmsg: 'operation time limit exceeded' }
244246
]
245247
});
@@ -268,10 +270,10 @@ describe('CSOT driver tests', () => {
268270
.catch(error => error);
269271
expect(error).to.be.instanceOf(MongoOperationTimeoutError);
270272
expect(error.cause).to.be.instanceOf(MongoServerError);
271-
expect(error.cause).to.have.nested.property('writeErrors[0].code', 50);
273+
expect(error.cause).to.have.nested.property('writeErrors[3].code', 50);
272274

273275
expect(commandsSucceeded).to.have.lengthOf(1);
274-
expect(commandsSucceeded).to.have.nested.property('[0].reply.writeErrors[0].code', 50);
276+
expect(commandsSucceeded).to.have.nested.property('[0].reply.writeErrors[3].code', 50);
275277
});
276278
});
277279

0 commit comments

Comments
 (0)