Skip to content

Commit

Permalink
chore: add looping for writeErrors
Browse files Browse the repository at this point in the history
  • Loading branch information
nbbeeken committed Aug 9, 2024
1 parent d2964ba commit 728ab9e
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 19 deletions.
5 changes: 4 additions & 1 deletion src/cmap/connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -621,7 +621,10 @@ export class Connection extends TypedEventEmitter<ConnectionEvents> {
}
} else {
if (
document?.writeErrors?.[0]?.code === MONGODB_ERROR_CODES.MaxTimeMSExpired ||
(Array.isArray(document?.writeErrors) &&
document.writeErrors.some(
error => error?.code === MONGODB_ERROR_CODES.MaxTimeMSExpired
)) ||
document?.writeConcernError?.code === MONGODB_ERROR_CODES.MaxTimeMSExpired
) {
throw new MongoOperationTimeoutError('Server reported a timeout error', {
Expand Down
37 changes: 25 additions & 12 deletions src/cmap/wire_protocol/responses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,18 +111,31 @@ export class MongoDBResponse extends OnDemandDocument {
* - ok is 1 and the writeConcern object contains a code === 50
*/
get isMaxTimeExpiredError() {
return (
// {ok: 0, code: 50 ... }
(this.ok === 0 && this.code === MONGODB_ERROR_CODES.MaxTimeMSExpired) ||
// {ok: 1, writeErrors: [{code: 50 ... }]}
(this.ok === 1 &&
this.get('writeErrors', BSONType.array)?.get(0, BSONType.object)?.getNumber('code') ===
MONGODB_ERROR_CODES.MaxTimeMSExpired) ||
// {ok: 1, writeConcernError: {code: 50 ... }}
(this.ok === 1 &&
this.get('writeConcernError', BSONType.object)?.getNumber('code') ===
MONGODB_ERROR_CODES.MaxTimeMSExpired)
);
// {ok: 0, code: 50 ... }
const isTopLevel = this.ok === 0 && this.code === MONGODB_ERROR_CODES.MaxTimeMSExpired;
if (isTopLevel) return true;

if (this.ok === 0) return false;

// {ok: 1, writeConcernError: {code: 50 ... }}
const isWriteConcern =
this.get('writeConcernError', BSONType.object)?.getNumber('code') ===
MONGODB_ERROR_CODES.MaxTimeMSExpired;
if (isWriteConcern) return true;

const writeErrors = this.get('writeErrors', BSONType.array);
if (writeErrors?.size()) {
for (let i = 0; i < writeErrors.size(); i++) {
const isWriteError =
writeErrors.get(i, BSONType.object)?.getNumber('code') ===
MONGODB_ERROR_CODES.MaxTimeMSExpired;

// {ok: 1, writeErrors: [{code: 50 ... }]}
if (isWriteError) return true;
}
}

return false;
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
/* Anything javascript specific relating to timeouts */
import { expect } from 'chai';
import * as semver from 'semver';
import * as sinon from 'sinon';

import {
BSON,
type ClientSession,
Code,
type Collection,
Connection,
type Db,
Expand Down Expand Up @@ -232,14 +232,16 @@ describe('CSOT driver tests', () => {
});

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

beforeEach(async () => {
const writeErrorsReply = BSON.serialize({
ok: 1,
writeErrors: [
{ code: 2, codeName: 'MaxTimeMSExpired', errmsg: 'operation time limit exceeded' },
{ code: 3, codeName: 'MaxTimeMSExpired', errmsg: 'operation time limit exceeded' },
{ code: 4, codeName: 'MaxTimeMSExpired', errmsg: 'operation time limit exceeded' },
{ code: 50, codeName: 'MaxTimeMSExpired', errmsg: 'operation time limit exceeded' }
]
});
Expand Down Expand Up @@ -268,10 +270,10 @@ describe('CSOT driver tests', () => {
.catch(error => error);
expect(error).to.be.instanceOf(MongoOperationTimeoutError);
expect(error.cause).to.be.instanceOf(MongoServerError);
expect(error.cause).to.have.nested.property('writeErrors[0].code', 50);
expect(error.cause).to.have.nested.property('writeErrors[3].code', 50);

expect(commandsSucceeded).to.have.lengthOf(1);
expect(commandsSucceeded).to.have.nested.property('[0].reply.writeErrors[0].code', 50);
expect(commandsSucceeded).to.have.nested.property('[0].reply.writeErrors[3].code', 50);
});
});

Expand Down

0 comments on commit 728ab9e

Please sign in to comment.