-
Notifications
You must be signed in to change notification settings - Fork 1.8k
fix(ChangeStream): should resume from errors when iterating #2360
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
Conversation
mbroadst
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice refactor for processError! This is looking really great, I've just got some questions and a few suggestions.
| }); | ||
|
|
||
| describe('Change Stream Resume Error Tests', function() { | ||
| function withChangeStream(testName, callback) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this might be useful as a more generalized helper withCursor, which we could alias to withChangeStream if that helps readability at all. Also, I think hiding a call to withClient in here might not be ideal since its sort of a side effect.
Finally, nitpick but testName seems to really be like collectionName?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Waiting on #2362 to see how to best address this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't ultimately find the withDb or withCollection helpers helped very much over there, but cursors are much more like clients, in that they have explicit close methods that sometimes need to be called.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a withCursor helper; it's a general-purpose wrapper around withClient. Is this roughly what you had in mind?
function withCursor(getCursor, callback) {
return withClient((client, done) => {
getCursor(client, (err, cursor) => {
if (err) return done(err);
callback(cursor, () => cursor.close(done));
});
});
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think of withX as a means of conveying the lifetime of a resource. So my thought with withCursor is that it would be like withClient, but not use withClient:
function withCursor(cursor, body) {
body(cursor, (err, result) => {
cursor.close(); // always close the cursor, this obviously would need to be async and handle errors etc
callback(...);
});
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it may not be worth the effort considering we have this.defer?
const cursor = coll.find();
this.defer(() => cursor.close());
cursor.toArray(...);
could work fine, but you might forget to put the defer in between creating the cursor and iterating it
| }); | ||
|
|
||
| describe('Change Stream Resume Error Tests', function() { | ||
| function withChangeStream(testName, callback) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't ultimately find the withDb or withCollection helpers helped very much over there, but cursors are much more like clients, in that they have explicit close methods that sometimes need to be called.
reggi
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
mbroadst
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
| * @param {(cursor: Object, done: Function) => void} body test body | ||
| * @param {Function} done called after cleanup | ||
| */ | ||
| function withCursor(cursor, body, done) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a thought, and not one I wanted to block this review on:
This helper doesn't account for tests which return a promise, which is a similar discussion to ones we've had previously in withClient and friends. I wonder if what we eventually want is some helper like withCloseable which is internally used by withClient, withMonitoredClient, withCursor and maybe even something like withSession (though this is an existing helper in the public API). Food for thought
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed it would be nice for withMonitoredClient and withCursor to support promises as well as callbacks, the way withClient does. I think refactoring to use withCloseable would be a nice reduction of duplicated logic but I don't see how it would add much utility. Perhaps it's something we can work into a future PR where we're trying to write promise-based tests that need monitored clients or cursors?
Description
Introduced
getCursormethod to safely provide a change stream cursorfor
next/hasNextacross recoveries from resumable errors.NODE-2548
What changed?
nextandhasNextnow usegetCursorprocessErrorwas extracted fromprocessNewChangewithCursorshared test helperAre there any files to ignore?