Skip to content

Commit 634ae4f

Browse files
authored
fix: make tryNext and Batch public (#2675)
Exposes the `tryNext` iteration helper on cursors and change streams. NODE-2952
1 parent 6914e87 commit 634ae4f

File tree

3 files changed

+27
-12
lines changed

3 files changed

+27
-12
lines changed

src/change_stream.ts

+26-9
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ const CHANGE_DOMAIN_TYPES = {
4646
const NO_RESUME_TOKEN_ERROR = new MongoError(
4747
'A change stream document has been received that lacks a resume token (_id).'
4848
);
49+
const NO_CURSOR_ERROR = new MongoError('ChangeStream has no cursor');
4950
const CHANGESTREAM_CLOSED_ERROR = new MongoError('ChangeStream is closed');
5051

5152
/** @public */
@@ -287,8 +288,7 @@ export class ChangeStream extends EventEmitter {
287288
next(callback?: Callback): Promise<void> | void {
288289
return maybePromise(callback, cb => {
289290
getCursor(this, (err, cursor) => {
290-
if (err) return cb(err); // failed to resume, raise an error
291-
if (!cursor) return cb(new MongoError('Cursor is undefined'));
291+
if (err || !cursor) return cb(err); // failed to resume, raise an error
292292
cursor.next((error, change) => {
293293
if (error) {
294294
this[kResumeQueue].push(() => this.next(cb));
@@ -330,11 +330,23 @@ export class ChangeStream extends EventEmitter {
330330
*/
331331
stream(options?: CursorStreamOptions): Readable {
332332
this.streamOptions = options;
333-
if (!this.cursor) {
334-
throw new MongoError('ChangeStream has no cursor, unable to stream');
335-
}
333+
if (!this.cursor) throw NO_CURSOR_ERROR;
336334
return this.cursor.stream(options);
337335
}
336+
337+
/**
338+
* Try to get the next available document from the Change Stream's cursor or `null` if an empty batch is returned
339+
*/
340+
tryNext(): Promise<Document | null>;
341+
tryNext(callback: Callback<Document | null>): void;
342+
tryNext(callback?: Callback<Document | null>): Promise<Document | null> | void {
343+
return maybePromise(callback, cb => {
344+
getCursor(this, (err, cursor) => {
345+
if (err || !cursor) return cb(err); // failed to resume, raise an error
346+
return cursor.tryNext(cb);
347+
});
348+
});
349+
}
338350
}
339351

340352
/** @internal */
@@ -707,11 +719,16 @@ function getCursor(changeStream: ChangeStream, callback: Callback<ChangeStreamCu
707719
function processResumeQueue(changeStream: ChangeStream, err?: Error) {
708720
while (changeStream[kResumeQueue].length) {
709721
const request = changeStream[kResumeQueue].pop();
710-
if (changeStream[kClosed] && !err) {
711-
request(CHANGESTREAM_CLOSED_ERROR);
712-
return;
722+
if (!err) {
723+
if (changeStream[kClosed]) {
724+
request(CHANGESTREAM_CLOSED_ERROR);
725+
return;
726+
}
727+
if (!changeStream.cursor) {
728+
request(NO_CURSOR_ERROR);
729+
return;
730+
}
713731
}
714-
715732
request(err, changeStream.cursor);
716733
}
717734
}

src/cursor/abstract_cursor.ts

-1
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,6 @@ export abstract class AbstractCursor extends EventEmitter {
265265

266266
/**
267267
* Try to get the next available document from the cursor or `null` if an empty batch is returned
268-
* @internal
269268
*/
270269
tryNext(): Promise<Document | null>;
271270
tryNext(callback: Callback<Document | null>): void;

test/functional/change_stream.test.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -1943,8 +1943,7 @@ describe('Change Streams', function () {
19431943
changeStream.on('change', () => {
19441944
counter += 1;
19451945
if (counter === 2) {
1946-
changeStream.close();
1947-
setTimeout(() => close());
1946+
changeStream.close(close);
19481947
} else if (counter >= 3) {
19491948
close(new Error('should not have received more than 2 events'));
19501949
}

0 commit comments

Comments
 (0)