Skip to content

Commit 1a2fd2b

Browse files
committed
fix(cursor): close underlying query cursor when calling destroy()
Fix Automattic#14966
1 parent 925327f commit 1a2fd2b

File tree

3 files changed

+43
-0
lines changed

3 files changed

+43
-0
lines changed

lib/cursor/queryCursor.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,27 @@ QueryCursor.prototype.close = async function close() {
238238
}
239239
};
240240

241+
/**
242+
* Marks this cursor as destroyed. Will stop streaming and subsequent calls to
243+
* `next()` will error.
244+
*
245+
* @return {this}
246+
* @api private
247+
* @method _destroy
248+
*/
249+
250+
QueryCursor.prototype._destroy = function _destroy(_err, callback) {
251+
this.cursor.close()
252+
.then(() => {
253+
this._closed = false;
254+
callback();
255+
})
256+
.catch(error => {
257+
callback(error);
258+
});
259+
return this;
260+
};
261+
241262
/**
242263
* Rewind this cursor to its uninitialized state. Any options that are present on the cursor will
243264
* remain in effect. Iterating this cursor will cause new queries to be sent to the server, even

test/query.cursor.test.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
'use strict';
66

7+
const { once } = require('events');
78
const start = require('./common');
89

910
const assert = require('assert');
@@ -920,6 +921,21 @@ describe('QueryCursor', function() {
920921
assert.ok(cursor.cursor);
921922
assert.equal(driverCursor, cursor.cursor);
922923
});
924+
925+
it('handles destroy() (gh-14966)', async function() {
926+
db.deleteModel(/Test/);
927+
const TestModel = db.model('Test', mongoose.Schema({ name: String }));
928+
929+
const stream = await TestModel.find().cursor();
930+
await once(stream, 'cursor');
931+
assert.ok(!stream.cursor.closed);
932+
933+
stream.destroy();
934+
935+
await once(stream.cursor, 'close');
936+
assert.ok(stream.destroyed);
937+
assert.ok(stream.cursor.closed);
938+
});
923939
});
924940

925941
async function delay(ms) {

types/cursor.d.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ declare module 'mongoose' {
2626
*/
2727
close(): Promise<void>;
2828

29+
/**
30+
* Destroy this cursor, closing the underlying cursor. Will stop streaming
31+
* and subsequent calls to `next()` will error.
32+
*/
33+
destroy(): this;
34+
2935
/**
3036
* Rewind this cursor to its uninitialized state. Any options that are present on the cursor will
3137
* remain in effect. Iterating this cursor will cause new queries to be sent to the server, even

0 commit comments

Comments
 (0)