Skip to content

Conversation

andymina
Copy link
Contributor

@andymina andymina commented Aug 6, 2021

Description

Unwrapped the nested errors seen in handleMongoWriteConcernError to be clearer and more readable.

@andymina andymina closed this Aug 6, 2021
@andymina andymina reopened this Aug 6, 2021
@andymina andymina marked this pull request as draft August 6, 2021 19:06
@andymina andymina self-assigned this Aug 6, 2021
@andymina andymina added the wip label Aug 6, 2021
@dariakp
Copy link
Contributor

dariakp commented Aug 6, 2021

@andymina we should be careful about removing the server error behavior of assigning all input object props to the error object; the function of the server error class is to wrap errors returned from the server, and I believe the original design was based around the idea that we might not always know what those properties are, so we just want to pass them on to the user so that they have that information from the server; removing this behavior is a potentially breaking change. The goal of the ticket was just to remove the explicit rewrapping of the write concern error, not necessarily change the actual implementation of the MongoServerError class.

@andymina
Copy link
Contributor Author

andymina commented Aug 6, 2021

@andymina we should be careful about removing the server error behavior of assigning all input object props to the error object; the function of the server error class is to wrap errors returned from the server, and I believe the original design was based around the idea that we might not always know what those properties are, so we just want to pass them on to the user so that they have that information from the server; removing this behavior is a potentially breaking change. The goal of the ticket was just to remove the explicit rewrapping of the write concern error, not necessarily change the actual implementation of the MongoServerError class.

@dariakp Ahh, didn't realize that there were potentially more/new props coming in from the server. Initially I figured that the shape of MongoServerErrors that the driver needs would remain the same so I just explicitly retrieved them rather than relying on the loop. So sorry for any confusion! Will revert this change, ty :)

src/error.ts Outdated
this.ok = message.ok;
this.topologyVersion = message.topologyVersion;

const currentProps = Object.getOwnPropertyNames(this);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is all this really necessary to simplify the multiple constructor calls in bulk/common? It looks like all this filtering is doing the same thing as the original for..in, but it's less efficient because of the multiple array function calls. Ideally, the server error class should not need to be touched at all to complete this ticket, and we definitely should not be adding new functionality to it unless absolutely necessary (referring to the kErrorLabels line above), so any logic that's specific to particular errors, and not all server errors, should live in those specific classes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neal and I talked things over and I removed the tons of array calls that were there. I opted to put prop names into a set for better efficiency and it'll likely be easier to read/maintain than loads of if conditions.

@andymina andymina removed the wip label Aug 9, 2021
@andymina andymina added the Primary Review In Review with primary reviewer, not yet ready for team's eyes label Aug 9, 2021
*/
export class WriteConcernError {
err: MongoServerError;
err: { code: number; errmsg: string; errInfo?: Document };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We technically have a breakage here, this is no longer instanceof MongoServerError but this was just relying on the key mapping logic of the MongoServerError constructor.
I think its fair to make this change, all the properties are still accessible. Of course, up for discussion:

Copy link
Contributor

@dariakp dariakp Aug 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean, technically, based on the spec, there shouldn't be an err property here at all, so we could consider saving err as a symbol (and perhaps replacing err with a deprecated getter); any thoughts on this? This class never extended Error, so losing the stack trace from a property that should never have even been exposed wouldn't really be an issue

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You want to map these props on to this class? I think that sounds good removes a layer of indirection (and we keep a getter to prevent breakage)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

something along the lines of defining a kErr symbol (maybe more descriptive) set equal to the { code, errmsg, errInfo } and then a public getter marked deprecated: get err() { return this[kErr] } so that we hopefully don't break any existing functionality in case someone is trying to read directly from the current err prop

if (result.writeConcernError) {
bulkResult.writeConcernErrors.push(new WriteConcernError(result.writeConcernError));
const { code, errmsg, errInfo } = result.writeConcernError;
bulkResult.writeConcernErrors.push(new WriteConcernError({ code, errmsg, errInfo }));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we have to change this back to result.writeConcernError, we might be losing properties in this destructuring.
We can make the constructor accept a more flexible type, it's still good that we have a better typed WriteConcernError class, but incase there are more properties in certain server versions we should have them automatically pass through here.

) {
mergeBatchResults(batch, bulkResult, undefined, err.result);

// TODO: Remove multiple levels of wrapping (NODE-3337)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can delete the TODO

super(error as Error);
Object.assign(this, error);
constructor(
x: { message: string; code: number; writeErrors?: WriteError[] } | WriteConcernError | AnyError,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can name this something a little more descriptive than x now.

result: BulkWriteResult
) {
super(x);
if (x instanceof Error) Object.assign(this, x);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe we put the assign behind the gate of instanceof Error since that was filtering for MongoServerErrors while testing.
We should move the assign to be the last call of the constructor ungated. (Or remove it all together and see if tests fail, but I defer to the team on seeing if that's acceptable).

if (err || res == null) return callback(err);
if (res.code) return callback(new MongoServerError(res));
if (res.writeErrors) return callback(new MongoServerError(res.writeErrors[0]));
if (res.writeErrors) return callback(new MongoWriteConcernError(res.writeErrors[0]));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this always correct? I don't think a writeError is always in the category of a WriteConcernError, but I could be wrong, lets sync to make sure this is correct

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Capturing what spoke about in person: This has been reverted to MongoServerError since not every write error is a write concern error. The ideal solution would be to make this a WriteError class, but that would call for some error hierarchy refactoring since WriteError isn't a child of anything and that would be out of scope.

@andymina andymina requested a review from nbbeeken August 10, 2021 18:51
@andymina andymina added Team Review Needs review from team and removed Primary Review In Review with primary reviewer, not yet ready for team's eyes labels Aug 10, 2021
@andymina andymina requested review from dariakp and emadum August 10, 2021 21:56
@andymina
Copy link
Contributor Author

Neal requested reviews from my laptop lol

*/
export class WriteConcernError {
err: MongoServerError;
err: { code: number; errmsg: string; errInfo?: Document };
Copy link
Contributor

@dariakp dariakp Aug 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean, technically, based on the spec, there shouldn't be an err property here at all, so we could consider saving err as a symbol (and perhaps replacing err with a deprecated getter); any thoughts on this? This class never extended Error, so losing the stack trace from a property that should never have even been exposed wouldn't really be an issue

Copy link
Contributor

@emadum emadum left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One small request, and there is a lint error to fix, otherwise LGTM though! 👍

@andymina andymina requested review from dariakp and emadum August 16, 2021 16:13
}

/**
* @internal
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does it make sense to mark this internal if it's explicitly intended as a backcompat option for users?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose my thinking was it avoids breaking runtime code but intentionally makes it inaccessible to TS but I realize that could be nearly equal in breakage.

lets go with making this interface public and not introduce all these specialized exceptions. Sorry @andymina my advice steered you here!!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No worries!

errmsg: string;
errInfo?: Document;
} {
// WriteConcernErrorData has been inlined as the return to avoid making it public
Copy link
Contributor

@dariakp dariakp Aug 16, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's the reasoning against making it public?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I figured it would be yet another type clouding the namespace relating to an unclearly layered WriteConcernError/WriteError/BulkError space. But it's an 🧅 that can be argued otherwise

@andymina andymina requested a review from dariakp August 16, 2021 19:22
Copy link
Contributor

@emadum emadum left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

Copy link
Contributor

@dariakp dariakp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM :)

Copy link
Contributor

@nbbeeken nbbeeken left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@nbbeeken nbbeeken changed the title refactor(NODE-3337): unwrap-WriteConcernError refactor(NODE-3337): unwrap WriteConcernError Aug 17, 2021
@nbbeeken nbbeeken merged commit 2cdbc08 into 4.1 Aug 17, 2021
@nbbeeken nbbeeken deleted the NODE-3337/unwrap-WriteConcernError branch August 17, 2021 15:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Team Review Needs review from team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants