Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(changeStream): properly handle changeStream event mid-close #1902

Merged
merged 2 commits into from Jan 23, 2019

Conversation

daprahamian
Copy link
Contributor

If a changeStream gets an event while it is in the middle of closing,
a race condition can occur where the event is still processed after
the stream has closed. This commit adds handling for this edge
case by returning an error to callbacks, rejecting promises,
and simply ignoring it in emitter mode.

Fixes NODE-1831

If a changeStream gets an event while it is in the middle of closing,
a race condition can occur where the event is still processed after
the stream has closed. This commit adds handling for this edge
case by returning an error to callbacks, rejecting promises,
and simply ignoring it in emitter mode.

Fixes NODE-1831
if (changeStream.isClosed()) {
if (eventEmitter) return;

const error = new Error('ChangeStream is closed');
Copy link
Member

Choose a reason for hiding this comment

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

I think this should be a MongoError right?

Copy link
Member

Choose a reason for hiding this comment

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

also nit, but should ChangeStream just be change stream? It makes it look like a product name 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.

Was referring to the class ChangeStream here. Figured it was better to specify the constructor object.

Also, I specifically resisted throwing a MongoError b/c right now we use MongoError mostly for server-side errors. We don't really have a concept of a MongoDriverError.

Copy link
Member

Choose a reason for hiding this comment

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

👍 on point one
For the second point, I still think it makes sense to mark it as a MongoError until such an error class exists. It makes it harder to catch errors generically limited to the driver if we also sometimes throw plain Error s, at very least even if/when a MongoDriverError is introduced it will be a subclass of MongoError

.then(() => changeStream.next())
.then(() => changeStream.next())
.then(() => {
const closeP = Promise.resolve().then(() => changeStream.close());
Copy link
Member

Choose a reason for hiding this comment

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

Interesting, does changeStream.close() not return a Promise? Looks like it should to me. This should at least be: Promise.resolve(changeStream.close())

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is actually a relic of when I was trying to enqueue changeStream.close as a microTask. I can remove it.

@@ -1677,4 +1677,133 @@ describe('Change Streams', function() {
.then(() => finish(), err => finish(err));
}
});

describe('should properly handle a changeStream event being processed mid-close', function() {
Copy link
Member

Choose a reason for hiding this comment

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

Is it possible to refactor these three tests to use the same setup/teardown code for a client, rather than clutter the tests with it? It also feels like you can use the same method to write data, as you're really only testing different APIs for reads here

Copy link
Contributor

@kvwalker kvwalker left a comment

Choose a reason for hiding this comment

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

👍

Copy link
Member

@mbroadst mbroadst left a comment

Choose a reason for hiding this comment

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

LGTM

@daprahamian daprahamian merged commit 5ad9fa9 into master Jan 23, 2019
@daprahamian daprahamian deleted the NODE-1831/change-stream-error branch January 23, 2019 00:04
kiku-jw pushed a commit to kiku-jw/node-mongodb-native that referenced this pull request Feb 11, 2019
…odb#1902)

If a changeStream gets an event while it is in the middle of closing,
a race condition can occur where the event is still processed after
the stream has closed. This commit adds handling for this edge
case by returning an error to callbacks, rejecting promises,
and simply ignoring it in emitter mode.

Fixes NODE-1831
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants