mongodb 6.7.0-dev.20240613.sha.c1af6adc → 6.7.0-dev.20240614.sha.3ed6a2ad
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/bson.js.map +1 -1
- package/lib/client-side-encryption/auto_encrypter.js +8 -61
- package/lib/client-side-encryption/auto_encrypter.js.map +1 -1
- package/lib/client-side-encryption/client_encryption.js +5 -5
- package/lib/client-side-encryption/client_encryption.js.map +1 -1
- package/lib/client-side-encryption/state_machine.js +15 -11
- package/lib/client-side-encryption/state_machine.js.map +1 -1
- package/lib/cmap/connection.js +22 -20
- package/lib/cmap/connection.js.map +1 -1
- package/lib/cmap/wire_protocol/on_demand/document.js +8 -5
- package/lib/cmap/wire_protocol/on_demand/document.js.map +1 -1
- package/lib/cmap/wire_protocol/responses.js +116 -40
- package/lib/cmap/wire_protocol/responses.js.map +1 -1
- package/lib/constants.js +9 -1
- package/lib/constants.js.map +1 -1
- package/lib/cursor/abstract_cursor.js +24 -60
- package/lib/cursor/abstract_cursor.js.map +1 -1
- package/lib/cursor/aggregation_cursor.js +2 -3
- package/lib/cursor/aggregation_cursor.js.map +1 -1
- package/lib/cursor/change_stream_cursor.js +6 -8
- package/lib/cursor/change_stream_cursor.js.map +1 -1
- package/lib/cursor/find_cursor.js +5 -17
- package/lib/cursor/find_cursor.js.map +1 -1
- package/lib/cursor/list_collections_cursor.js +0 -1
- package/lib/cursor/list_collections_cursor.js.map +1 -1
- package/lib/cursor/list_indexes_cursor.js +0 -1
- package/lib/cursor/list_indexes_cursor.js.map +1 -1
- package/lib/cursor/run_command_cursor.js +4 -6
- package/lib/cursor/run_command_cursor.js.map +1 -1
- package/lib/error.js +6 -21
- package/lib/error.js.map +1 -1
- package/lib/operations/aggregate.js +2 -2
- package/lib/operations/aggregate.js.map +1 -1
- package/lib/operations/bulk_write.js +1 -2
- package/lib/operations/bulk_write.js.map +1 -1
- package/lib/operations/command.js +2 -3
- package/lib/operations/command.js.map +1 -1
- package/lib/operations/count_documents.js +1 -7
- package/lib/operations/count_documents.js.map +1 -1
- package/lib/operations/execute_operation.js.map +1 -1
- package/lib/operations/find.js +2 -1
- package/lib/operations/find.js.map +1 -1
- package/lib/operations/get_more.js +1 -1
- package/lib/operations/get_more.js.map +1 -1
- package/lib/operations/indexes.js +2 -1
- package/lib/operations/indexes.js.map +1 -1
- package/lib/operations/list_collections.js +2 -1
- package/lib/operations/list_collections.js.map +1 -1
- package/lib/operations/run_command.js +1 -1
- package/lib/operations/run_command.js.map +1 -1
- package/lib/operations/update.js +2 -1
- package/lib/operations/update.js.map +1 -1
- package/lib/sdam/server.js +7 -2
- package/lib/sdam/server.js.map +1 -1
- package/lib/utils.js +45 -1
- package/lib/utils.js.map +1 -1
- package/lib/write_concern.js +17 -1
- package/lib/write_concern.js.map +1 -1
- package/mongodb.d.ts +17 -8
- package/package.json +1 -1
- package/src/bson.ts +1 -0
- package/src/client-side-encryption/auto_encrypter.ts +9 -70
- package/src/client-side-encryption/client_encryption.ts +6 -6
- package/src/client-side-encryption/state_machine.ts +18 -16
- package/src/cmap/connection.ts +46 -50
- package/src/cmap/wire_protocol/on_demand/document.ts +13 -6
- package/src/cmap/wire_protocol/responses.ts +140 -45
- package/src/constants.ts +9 -0
- package/src/cursor/abstract_cursor.ts +51 -71
- package/src/cursor/aggregation_cursor.ts +13 -12
- package/src/cursor/change_stream_cursor.ts +20 -34
- package/src/cursor/find_cursor.ts +17 -25
- package/src/cursor/list_collections_cursor.ts +3 -4
- package/src/cursor/list_indexes_cursor.ts +3 -4
- package/src/cursor/run_command_cursor.ts +13 -19
- package/src/error.ts +16 -28
- package/src/index.ts +6 -7
- package/src/operations/aggregate.ts +12 -5
- package/src/operations/bulk_write.ts +1 -2
- package/src/operations/command.ts +17 -3
- package/src/operations/count_documents.ts +7 -11
- package/src/operations/delete.ts +2 -2
- package/src/operations/execute_operation.ts +0 -13
- package/src/operations/find.ts +7 -3
- package/src/operations/find_and_modify.ts +1 -1
- package/src/operations/get_more.ts +6 -10
- package/src/operations/indexes.ts +7 -3
- package/src/operations/list_collections.ts +8 -3
- package/src/operations/run_command.ts +16 -6
- package/src/operations/update.ts +2 -1
- package/src/sdam/server.ts +7 -2
- package/src/utils.ts +52 -2
- package/src/write_concern.ts +18 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Readable, Transform } from 'stream';
|
|
2
2
|
|
|
3
3
|
import { type BSONSerializeOptions, type Document, Long, pluckBSONSerializeOptions } from '../bson';
|
|
4
|
-
import { CursorResponse } from '../cmap/wire_protocol/responses';
|
|
4
|
+
import { type CursorResponse } from '../cmap/wire_protocol/responses';
|
|
5
5
|
import {
|
|
6
6
|
MongoAPIError,
|
|
7
7
|
MongoCursorExhaustedError,
|
|
@@ -11,15 +11,33 @@ import {
|
|
|
11
11
|
MongoTailableCursorError
|
|
12
12
|
} from '../error';
|
|
13
13
|
import type { MongoClient } from '../mongo_client';
|
|
14
|
-
import {
|
|
15
|
-
import { executeOperation
|
|
14
|
+
import { TypedEventEmitter } from '../mongo_types';
|
|
15
|
+
import { executeOperation } from '../operations/execute_operation';
|
|
16
16
|
import { GetMoreOperation } from '../operations/get_more';
|
|
17
17
|
import { KillCursorsOperation } from '../operations/kill_cursors';
|
|
18
18
|
import { ReadConcern, type ReadConcernLike } from '../read_concern';
|
|
19
19
|
import { ReadPreference, type ReadPreferenceLike } from '../read_preference';
|
|
20
20
|
import type { Server } from '../sdam/server';
|
|
21
21
|
import { ClientSession, maybeClearPinnedConnection } from '../sessions';
|
|
22
|
-
import {
|
|
22
|
+
import { type MongoDBNamespace, squashError } from '../utils';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @internal
|
|
26
|
+
* TODO(NODE-2882): A cursor's getMore commands must be run on the same server it was started on
|
|
27
|
+
* and the same session must be used for the lifetime of the cursor. This object serves to get the
|
|
28
|
+
* server and session (along with the response) out of executeOperation back to the AbstractCursor.
|
|
29
|
+
*
|
|
30
|
+
* There may be a better design for communicating these values back to the cursor, currently an operation
|
|
31
|
+
* MUST store the selected server on itself so it can be read after executeOperation has returned.
|
|
32
|
+
*/
|
|
33
|
+
export interface InitialCursorResponse {
|
|
34
|
+
/** The server selected for the operation */
|
|
35
|
+
server: Server;
|
|
36
|
+
/** The session used for this operation, may be implicitly created */
|
|
37
|
+
session?: ClientSession;
|
|
38
|
+
/** The raw server response for the operation */
|
|
39
|
+
response: CursorResponse;
|
|
40
|
+
}
|
|
23
41
|
|
|
24
42
|
/** @public */
|
|
25
43
|
export const CURSOR_FLAGS = [
|
|
@@ -118,13 +136,7 @@ export abstract class AbstractCursor<
|
|
|
118
136
|
/** @internal */
|
|
119
137
|
private cursorNamespace: MongoDBNamespace;
|
|
120
138
|
/** @internal */
|
|
121
|
-
private documents:
|
|
122
|
-
length: number;
|
|
123
|
-
shift(bsonOptions?: any): TSchema | null;
|
|
124
|
-
clear(): void;
|
|
125
|
-
pushMany(many: Iterable<TSchema>): void;
|
|
126
|
-
push(item: TSchema): void;
|
|
127
|
-
};
|
|
139
|
+
private documents: CursorResponse | null = null;
|
|
128
140
|
/** @internal */
|
|
129
141
|
private cursorClient: MongoClient;
|
|
130
142
|
/** @internal */
|
|
@@ -155,7 +167,6 @@ export abstract class AbstractCursor<
|
|
|
155
167
|
this.cursorClient = client;
|
|
156
168
|
this.cursorNamespace = namespace;
|
|
157
169
|
this.cursorId = null;
|
|
158
|
-
this.documents = new List();
|
|
159
170
|
this.initialized = false;
|
|
160
171
|
this.isClosed = false;
|
|
161
172
|
this.isKilled = false;
|
|
@@ -252,16 +263,19 @@ export abstract class AbstractCursor<
|
|
|
252
263
|
|
|
253
264
|
/** Returns current buffered documents length */
|
|
254
265
|
bufferedCount(): number {
|
|
255
|
-
return this.documents
|
|
266
|
+
return this.documents?.length ?? 0;
|
|
256
267
|
}
|
|
257
268
|
|
|
258
269
|
/** Returns current buffered documents */
|
|
259
270
|
readBufferedDocuments(number?: number): TSchema[] {
|
|
260
271
|
const bufferedDocs: TSchema[] = [];
|
|
261
|
-
const documentsToRead = Math.min(
|
|
272
|
+
const documentsToRead = Math.min(
|
|
273
|
+
number ?? this.documents?.length ?? 0,
|
|
274
|
+
this.documents?.length ?? 0
|
|
275
|
+
);
|
|
262
276
|
|
|
263
277
|
for (let count = 0; count < documentsToRead; count++) {
|
|
264
|
-
const document = this.documents
|
|
278
|
+
const document = this.documents?.shift(this.cursorOptions);
|
|
265
279
|
if (document != null) {
|
|
266
280
|
bufferedDocs.push(document);
|
|
267
281
|
}
|
|
@@ -269,7 +283,6 @@ export abstract class AbstractCursor<
|
|
|
269
283
|
|
|
270
284
|
return bufferedDocs;
|
|
271
285
|
}
|
|
272
|
-
|
|
273
286
|
async *[Symbol.asyncIterator](): AsyncGenerator<TSchema, void, void> {
|
|
274
287
|
if (this.isClosed) {
|
|
275
288
|
return;
|
|
@@ -281,11 +294,11 @@ export abstract class AbstractCursor<
|
|
|
281
294
|
return;
|
|
282
295
|
}
|
|
283
296
|
|
|
284
|
-
if (this.
|
|
297
|
+
if (this.closed && (this.documents?.length ?? 0) === 0) {
|
|
285
298
|
return;
|
|
286
299
|
}
|
|
287
300
|
|
|
288
|
-
if (this.cursorId != null && this.isDead && this.documents
|
|
301
|
+
if (this.cursorId != null && this.isDead && (this.documents?.length ?? 0) === 0) {
|
|
289
302
|
return;
|
|
290
303
|
}
|
|
291
304
|
|
|
@@ -347,11 +360,11 @@ export abstract class AbstractCursor<
|
|
|
347
360
|
}
|
|
348
361
|
|
|
349
362
|
do {
|
|
350
|
-
if (this.documents
|
|
363
|
+
if ((this.documents?.length ?? 0) !== 0) {
|
|
351
364
|
return true;
|
|
352
365
|
}
|
|
353
366
|
await this.fetchBatch();
|
|
354
|
-
} while (!this.isDead || this.documents
|
|
367
|
+
} while (!this.isDead || (this.documents?.length ?? 0) !== 0);
|
|
355
368
|
|
|
356
369
|
return false;
|
|
357
370
|
}
|
|
@@ -363,13 +376,13 @@ export abstract class AbstractCursor<
|
|
|
363
376
|
}
|
|
364
377
|
|
|
365
378
|
do {
|
|
366
|
-
const doc = this.documents
|
|
379
|
+
const doc = this.documents?.shift(this.cursorOptions);
|
|
367
380
|
if (doc != null) {
|
|
368
381
|
if (this.transform != null) return await this.transformDocument(doc);
|
|
369
382
|
return doc;
|
|
370
383
|
}
|
|
371
384
|
await this.fetchBatch();
|
|
372
|
-
} while (!this.isDead || this.documents
|
|
385
|
+
} while (!this.isDead || (this.documents?.length ?? 0) !== 0);
|
|
373
386
|
|
|
374
387
|
return null;
|
|
375
388
|
}
|
|
@@ -382,7 +395,7 @@ export abstract class AbstractCursor<
|
|
|
382
395
|
throw new MongoCursorExhaustedError();
|
|
383
396
|
}
|
|
384
397
|
|
|
385
|
-
let doc = this.documents
|
|
398
|
+
let doc = this.documents?.shift(this.cursorOptions);
|
|
386
399
|
if (doc != null) {
|
|
387
400
|
if (this.transform != null) return await this.transformDocument(doc);
|
|
388
401
|
return doc;
|
|
@@ -390,7 +403,7 @@ export abstract class AbstractCursor<
|
|
|
390
403
|
|
|
391
404
|
await this.fetchBatch();
|
|
392
405
|
|
|
393
|
-
doc = this.documents
|
|
406
|
+
doc = this.documents?.shift(this.cursorOptions);
|
|
394
407
|
if (doc != null) {
|
|
395
408
|
if (this.transform != null) return await this.transformDocument(doc);
|
|
396
409
|
return doc;
|
|
@@ -591,7 +604,7 @@ export abstract class AbstractCursor<
|
|
|
591
604
|
}
|
|
592
605
|
|
|
593
606
|
this.cursorId = null;
|
|
594
|
-
this.documents
|
|
607
|
+
this.documents?.clear();
|
|
595
608
|
this.isClosed = false;
|
|
596
609
|
this.isKilled = false;
|
|
597
610
|
this.initialized = false;
|
|
@@ -615,10 +628,12 @@ export abstract class AbstractCursor<
|
|
|
615
628
|
abstract clone(): AbstractCursor<TSchema>;
|
|
616
629
|
|
|
617
630
|
/** @internal */
|
|
618
|
-
protected abstract _initialize(
|
|
631
|
+
protected abstract _initialize(
|
|
632
|
+
session: ClientSession | undefined
|
|
633
|
+
): Promise<InitialCursorResponse>;
|
|
619
634
|
|
|
620
635
|
/** @internal */
|
|
621
|
-
async getMore(batchSize: number
|
|
636
|
+
async getMore(batchSize: number): Promise<CursorResponse> {
|
|
622
637
|
if (this.cursorId == null) {
|
|
623
638
|
throw new MongoRuntimeError(
|
|
624
639
|
'Unexpected null cursor id. A cursor creating command should have set this'
|
|
@@ -636,8 +651,7 @@ export abstract class AbstractCursor<
|
|
|
636
651
|
{
|
|
637
652
|
...this.cursorOptions,
|
|
638
653
|
session: this.cursorSession,
|
|
639
|
-
batchSize
|
|
640
|
-
useCursorResponse
|
|
654
|
+
batchSize
|
|
641
655
|
}
|
|
642
656
|
);
|
|
643
657
|
|
|
@@ -656,27 +670,10 @@ export abstract class AbstractCursor<
|
|
|
656
670
|
const state = await this._initialize(this.cursorSession);
|
|
657
671
|
const response = state.response;
|
|
658
672
|
this.selectedServer = state.server;
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
} else if (response.cursor) {
|
|
664
|
-
// TODO(NODE-2674): Preserve int64 sent from MongoDB
|
|
665
|
-
this.cursorId = getCursorId(response);
|
|
666
|
-
if (response.cursor.ns) this.cursorNamespace = ns(response.cursor.ns);
|
|
667
|
-
this.documents.pushMany(response.cursor.firstBatch);
|
|
668
|
-
}
|
|
669
|
-
|
|
670
|
-
if (this.cursorId == null) {
|
|
671
|
-
// When server responses return without a cursor document, we close this cursor
|
|
672
|
-
// and return the raw server response. This is the case for explain commands
|
|
673
|
-
this.cursorId = Long.ZERO;
|
|
674
|
-
// TODO(NODE-3286): ExecutionResult needs to accept a generic parameter
|
|
675
|
-
this.documents.push(state.response as TODO_NODE_3286);
|
|
676
|
-
}
|
|
677
|
-
|
|
678
|
-
// the cursor is now initialized, even if it is dead
|
|
679
|
-
this.initialized = true;
|
|
673
|
+
this.cursorId = response.id;
|
|
674
|
+
this.cursorNamespace = response.ns ?? this.namespace;
|
|
675
|
+
this.documents = response;
|
|
676
|
+
this.initialized = true; // the cursor is now initialized, even if it is dead
|
|
680
677
|
} catch (error) {
|
|
681
678
|
// the cursor is now initialized, even if an error occurred
|
|
682
679
|
this.initialized = true;
|
|
@@ -708,7 +705,7 @@ export abstract class AbstractCursor<
|
|
|
708
705
|
if (this.cursorId == null) {
|
|
709
706
|
await this.cursorInit();
|
|
710
707
|
// If the cursor died or returned documents, return
|
|
711
|
-
if (this.documents
|
|
708
|
+
if ((this.documents?.length ?? 0) !== 0 || this.isDead) return;
|
|
712
709
|
// Otherwise, run a getMore
|
|
713
710
|
}
|
|
714
711
|
|
|
@@ -717,16 +714,8 @@ export abstract class AbstractCursor<
|
|
|
717
714
|
|
|
718
715
|
try {
|
|
719
716
|
const response = await this.getMore(batchSize);
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
if (CursorResponse.is(response)) {
|
|
723
|
-
this.cursorId = response.id;
|
|
724
|
-
this.documents = response;
|
|
725
|
-
} else if (response?.cursor) {
|
|
726
|
-
const cursorId = getCursorId(response);
|
|
727
|
-
this.documents.pushMany(response.cursor.nextBatch);
|
|
728
|
-
this.cursorId = cursorId;
|
|
729
|
-
}
|
|
717
|
+
this.cursorId = response.id;
|
|
718
|
+
this.documents = response;
|
|
730
719
|
} catch (error) {
|
|
731
720
|
try {
|
|
732
721
|
await this.cleanup(error);
|
|
@@ -789,7 +778,7 @@ export abstract class AbstractCursor<
|
|
|
789
778
|
/** @internal */
|
|
790
779
|
private emitClose() {
|
|
791
780
|
try {
|
|
792
|
-
if (!this.hasEmittedClose && (this.documents
|
|
781
|
+
if (!this.hasEmittedClose && ((this.documents?.length ?? 0) === 0 || this.isClosed)) {
|
|
793
782
|
// @ts-expect-error: CursorEvents is generic so Parameters<CursorEvents["close"]> may not be assignable to `[]`. Not sure how to require extenders do not add parameters.
|
|
794
783
|
this.emit('close');
|
|
795
784
|
}
|
|
@@ -827,15 +816,6 @@ export abstract class AbstractCursor<
|
|
|
827
816
|
}
|
|
828
817
|
}
|
|
829
818
|
|
|
830
|
-
/** A temporary helper to box up the many possible type issue of cursor ids */
|
|
831
|
-
function getCursorId(response: Document) {
|
|
832
|
-
return typeof response.cursor.id === 'number'
|
|
833
|
-
? Long.fromNumber(response.cursor.id)
|
|
834
|
-
: typeof response.cursor.id === 'bigint'
|
|
835
|
-
? Long.fromBigInt(response.cursor.id)
|
|
836
|
-
: response.cursor.id;
|
|
837
|
-
}
|
|
838
|
-
|
|
839
819
|
class ReadableCursorStream extends Readable {
|
|
840
820
|
private _cursor: AbstractCursor;
|
|
841
821
|
private _readInProgress = false;
|
|
@@ -2,12 +2,12 @@ import type { Document } from '../bson';
|
|
|
2
2
|
import type { ExplainVerbosityLike } from '../explain';
|
|
3
3
|
import type { MongoClient } from '../mongo_client';
|
|
4
4
|
import { AggregateOperation, type AggregateOptions } from '../operations/aggregate';
|
|
5
|
-
import { executeOperation
|
|
5
|
+
import { executeOperation } from '../operations/execute_operation';
|
|
6
6
|
import type { ClientSession } from '../sessions';
|
|
7
7
|
import type { Sort } from '../sort';
|
|
8
8
|
import type { MongoDBNamespace } from '../utils';
|
|
9
9
|
import { mergeOptions } from '../utils';
|
|
10
|
-
import type { AbstractCursorOptions } from './abstract_cursor';
|
|
10
|
+
import type { AbstractCursorOptions, InitialCursorResponse } from './abstract_cursor';
|
|
11
11
|
import { AbstractCursor } from './abstract_cursor';
|
|
12
12
|
|
|
13
13
|
/** @public */
|
|
@@ -51,7 +51,7 @@ export class AggregationCursor<TSchema = any> extends AbstractCursor<TSchema> {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
/** @internal */
|
|
54
|
-
async _initialize(session: ClientSession): Promise<
|
|
54
|
+
async _initialize(session: ClientSession): Promise<InitialCursorResponse> {
|
|
55
55
|
const aggregateOperation = new AggregateOperation(this.namespace, this.pipeline, {
|
|
56
56
|
...this.aggregateOptions,
|
|
57
57
|
...this.cursorOptions,
|
|
@@ -60,20 +60,21 @@ export class AggregationCursor<TSchema = any> extends AbstractCursor<TSchema> {
|
|
|
60
60
|
|
|
61
61
|
const response = await executeOperation(this.client, aggregateOperation);
|
|
62
62
|
|
|
63
|
-
// TODO: NODE-2882
|
|
64
63
|
return { server: aggregateOperation.server, session, response };
|
|
65
64
|
}
|
|
66
65
|
|
|
67
66
|
/** Execute the explain for the cursor */
|
|
68
67
|
async explain(verbosity?: ExplainVerbosityLike): Promise<Document> {
|
|
69
|
-
return
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
68
|
+
return (
|
|
69
|
+
await executeOperation(
|
|
70
|
+
this.client,
|
|
71
|
+
new AggregateOperation(this.namespace, this.pipeline, {
|
|
72
|
+
...this.aggregateOptions, // NOTE: order matters here, we may need to refine this
|
|
73
|
+
...this.cursorOptions,
|
|
74
|
+
explain: verbosity ?? true
|
|
75
|
+
})
|
|
76
|
+
)
|
|
77
|
+
).shift(this.aggregateOptions);
|
|
77
78
|
}
|
|
78
79
|
|
|
79
80
|
/** Add a stage to the aggregation pipeline
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Document
|
|
1
|
+
import type { Document } from '../bson';
|
|
2
2
|
import {
|
|
3
3
|
ChangeStream,
|
|
4
4
|
type ChangeStreamDocument,
|
|
@@ -6,15 +6,19 @@ import {
|
|
|
6
6
|
type OperationTime,
|
|
7
7
|
type ResumeToken
|
|
8
8
|
} from '../change_stream';
|
|
9
|
+
import { type CursorResponse } from '../cmap/wire_protocol/responses';
|
|
9
10
|
import { INIT, RESPONSE } from '../constants';
|
|
10
11
|
import type { MongoClient } from '../mongo_client';
|
|
11
|
-
import type { TODO_NODE_3286 } from '../mongo_types';
|
|
12
12
|
import { AggregateOperation } from '../operations/aggregate';
|
|
13
13
|
import type { CollationOptions } from '../operations/command';
|
|
14
|
-
import { executeOperation
|
|
14
|
+
import { executeOperation } from '../operations/execute_operation';
|
|
15
15
|
import type { ClientSession } from '../sessions';
|
|
16
16
|
import { maxWireVersion, type MongoDBNamespace } from '../utils';
|
|
17
|
-
import {
|
|
17
|
+
import {
|
|
18
|
+
AbstractCursor,
|
|
19
|
+
type AbstractCursorOptions,
|
|
20
|
+
type InitialCursorResponse
|
|
21
|
+
} from './abstract_cursor';
|
|
18
22
|
|
|
19
23
|
/** @internal */
|
|
20
24
|
export interface ChangeStreamCursorOptions extends AbstractCursorOptions {
|
|
@@ -26,25 +30,13 @@ export interface ChangeStreamCursorOptions extends AbstractCursorOptions {
|
|
|
26
30
|
fullDocument?: string;
|
|
27
31
|
}
|
|
28
32
|
|
|
29
|
-
/** @internal */
|
|
30
|
-
export type ChangeStreamAggregateRawResult<TChange> = {
|
|
31
|
-
$clusterTime: { clusterTime: Timestamp };
|
|
32
|
-
cursor: {
|
|
33
|
-
postBatchResumeToken: ResumeToken;
|
|
34
|
-
ns: string;
|
|
35
|
-
id: number | Long;
|
|
36
|
-
} & ({ firstBatch: TChange[] } | { nextBatch: TChange[] });
|
|
37
|
-
ok: 1;
|
|
38
|
-
operationTime: Timestamp;
|
|
39
|
-
};
|
|
40
|
-
|
|
41
33
|
/** @internal */
|
|
42
34
|
export class ChangeStreamCursor<
|
|
43
35
|
TSchema extends Document = Document,
|
|
44
36
|
TChange extends Document = ChangeStreamDocument<TSchema>
|
|
45
37
|
> extends AbstractCursor<TChange, ChangeStreamEvents> {
|
|
46
38
|
private _resumeToken: ResumeToken;
|
|
47
|
-
private startAtOperationTime
|
|
39
|
+
private startAtOperationTime: OperationTime | null;
|
|
48
40
|
private hasReceived?: boolean;
|
|
49
41
|
private readonly changeStreamCursorOptions: ChangeStreamCursorOptions;
|
|
50
42
|
private postBatchResumeToken?: ResumeToken;
|
|
@@ -68,7 +60,7 @@ export class ChangeStreamCursor<
|
|
|
68
60
|
this.pipeline = pipeline;
|
|
69
61
|
this.changeStreamCursorOptions = options;
|
|
70
62
|
this._resumeToken = null;
|
|
71
|
-
this.startAtOperationTime = options.startAtOperationTime;
|
|
63
|
+
this.startAtOperationTime = options.startAtOperationTime ?? null;
|
|
72
64
|
|
|
73
65
|
if (options.startAfter) {
|
|
74
66
|
this.resumeToken = options.startAfter;
|
|
@@ -117,15 +109,13 @@ export class ChangeStreamCursor<
|
|
|
117
109
|
this.hasReceived = true;
|
|
118
110
|
}
|
|
119
111
|
|
|
120
|
-
_processBatch(response:
|
|
121
|
-
const
|
|
122
|
-
if (
|
|
123
|
-
this.postBatchResumeToken =
|
|
112
|
+
_processBatch(response: CursorResponse): void {
|
|
113
|
+
const { postBatchResumeToken } = response;
|
|
114
|
+
if (postBatchResumeToken) {
|
|
115
|
+
this.postBatchResumeToken = postBatchResumeToken;
|
|
124
116
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
if (batch.length === 0) {
|
|
128
|
-
this.resumeToken = cursor.postBatchResumeToken;
|
|
117
|
+
if (response.batchSize === 0) {
|
|
118
|
+
this.resumeToken = postBatchResumeToken;
|
|
129
119
|
}
|
|
130
120
|
}
|
|
131
121
|
}
|
|
@@ -136,17 +126,14 @@ export class ChangeStreamCursor<
|
|
|
136
126
|
});
|
|
137
127
|
}
|
|
138
128
|
|
|
139
|
-
async _initialize(session: ClientSession): Promise<
|
|
129
|
+
async _initialize(session: ClientSession): Promise<InitialCursorResponse> {
|
|
140
130
|
const aggregateOperation = new AggregateOperation(this.namespace, this.pipeline, {
|
|
141
131
|
...this.cursorOptions,
|
|
142
132
|
...this.changeStreamCursorOptions,
|
|
143
133
|
session
|
|
144
134
|
});
|
|
145
135
|
|
|
146
|
-
const response = await executeOperation
|
|
147
|
-
TODO_NODE_3286,
|
|
148
|
-
ChangeStreamAggregateRawResult<TChange>
|
|
149
|
-
>(session.client, aggregateOperation);
|
|
136
|
+
const response = await executeOperation(session.client, aggregateOperation);
|
|
150
137
|
|
|
151
138
|
const server = aggregateOperation.server;
|
|
152
139
|
this.maxWireVersion = maxWireVersion(server);
|
|
@@ -165,15 +152,14 @@ export class ChangeStreamCursor<
|
|
|
165
152
|
this.emit(INIT, response);
|
|
166
153
|
this.emit(RESPONSE);
|
|
167
154
|
|
|
168
|
-
// TODO: NODE-2882
|
|
169
155
|
return { server, session, response };
|
|
170
156
|
}
|
|
171
157
|
|
|
172
|
-
override async getMore(batchSize: number): Promise<
|
|
158
|
+
override async getMore(batchSize: number): Promise<CursorResponse> {
|
|
173
159
|
const response = await super.getMore(batchSize);
|
|
174
160
|
|
|
175
161
|
this.maxWireVersion = maxWireVersion(this.server);
|
|
176
|
-
this._processBatch(response
|
|
162
|
+
this._processBatch(response);
|
|
177
163
|
|
|
178
164
|
this.emit(ChangeStream.MORE, response);
|
|
179
165
|
this.emit(ChangeStream.RESPONSE);
|
|
@@ -5,13 +5,13 @@ import { type ExplainVerbosityLike } from '../explain';
|
|
|
5
5
|
import type { MongoClient } from '../mongo_client';
|
|
6
6
|
import type { CollationOptions } from '../operations/command';
|
|
7
7
|
import { CountOperation, type CountOptions } from '../operations/count';
|
|
8
|
-
import { executeOperation
|
|
8
|
+
import { executeOperation } from '../operations/execute_operation';
|
|
9
9
|
import { FindOperation, type FindOptions } from '../operations/find';
|
|
10
10
|
import type { Hint } from '../operations/operation';
|
|
11
11
|
import type { ClientSession } from '../sessions';
|
|
12
12
|
import { formatSort, type Sort, type SortDirection } from '../sort';
|
|
13
13
|
import { emitWarningOnce, mergeOptions, type MongoDBNamespace, squashError } from '../utils';
|
|
14
|
-
import { AbstractCursor } from './abstract_cursor';
|
|
14
|
+
import { AbstractCursor, type InitialCursorResponse } from './abstract_cursor';
|
|
15
15
|
|
|
16
16
|
/** @public Flags allowed for cursor */
|
|
17
17
|
export const FLAGS = [
|
|
@@ -62,7 +62,7 @@ export class FindCursor<TSchema = any> extends AbstractCursor<TSchema> {
|
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
/** @internal */
|
|
65
|
-
async _initialize(session: ClientSession): Promise<
|
|
65
|
+
async _initialize(session: ClientSession): Promise<InitialCursorResponse> {
|
|
66
66
|
const findOperation = new FindOperation(this.namespace, this.cursorFilter, {
|
|
67
67
|
...this.findOptions, // NOTE: order matters here, we may need to refine this
|
|
68
68
|
...this.cursorOptions,
|
|
@@ -72,19 +72,13 @@ export class FindCursor<TSchema = any> extends AbstractCursor<TSchema> {
|
|
|
72
72
|
const response = await executeOperation(this.client, findOperation);
|
|
73
73
|
|
|
74
74
|
// the response is not a cursor when `explain` is enabled
|
|
75
|
-
|
|
76
|
-
this.numReturned = response.batchSize;
|
|
77
|
-
} else {
|
|
78
|
-
// Can be an explain response, hence the ?. on everything
|
|
79
|
-
this.numReturned = this.numReturned + (response?.cursor?.firstBatch?.length ?? 0);
|
|
80
|
-
}
|
|
75
|
+
this.numReturned = response.batchSize;
|
|
81
76
|
|
|
82
|
-
// TODO: NODE-2882
|
|
83
77
|
return { server: findOperation.server, session, response };
|
|
84
78
|
}
|
|
85
79
|
|
|
86
80
|
/** @internal */
|
|
87
|
-
override async getMore(batchSize: number): Promise<
|
|
81
|
+
override async getMore(batchSize: number): Promise<CursorResponse> {
|
|
88
82
|
const numReturned = this.numReturned;
|
|
89
83
|
if (numReturned) {
|
|
90
84
|
// TODO(DRIVERS-1448): Remove logic to enforce `limit` in the driver
|
|
@@ -110,13 +104,9 @@ export class FindCursor<TSchema = any> extends AbstractCursor<TSchema> {
|
|
|
110
104
|
}
|
|
111
105
|
}
|
|
112
106
|
|
|
113
|
-
const response = await super.getMore(batchSize
|
|
107
|
+
const response = await super.getMore(batchSize);
|
|
114
108
|
// TODO: wrap this in some logic to prevent it from happening if we don't need this support
|
|
115
|
-
|
|
116
|
-
this.numReturned = this.numReturned + response.batchSize;
|
|
117
|
-
} else {
|
|
118
|
-
this.numReturned = this.numReturned + (response?.cursor?.nextBatch?.length ?? 0);
|
|
119
|
-
}
|
|
109
|
+
this.numReturned = this.numReturned + response.batchSize;
|
|
120
110
|
|
|
121
111
|
return response;
|
|
122
112
|
}
|
|
@@ -144,14 +134,16 @@ export class FindCursor<TSchema = any> extends AbstractCursor<TSchema> {
|
|
|
144
134
|
|
|
145
135
|
/** Execute the explain for the cursor */
|
|
146
136
|
async explain(verbosity?: ExplainVerbosityLike): Promise<Document> {
|
|
147
|
-
return
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
137
|
+
return (
|
|
138
|
+
await executeOperation(
|
|
139
|
+
this.client,
|
|
140
|
+
new FindOperation(this.namespace, this.cursorFilter, {
|
|
141
|
+
...this.findOptions, // NOTE: order matters here, we may need to refine this
|
|
142
|
+
...this.cursorOptions,
|
|
143
|
+
explain: verbosity ?? true
|
|
144
|
+
})
|
|
145
|
+
)
|
|
146
|
+
).shift(this.findOptions);
|
|
155
147
|
}
|
|
156
148
|
|
|
157
149
|
/** Set the cursor query */
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import type { Document } from '../bson';
|
|
2
2
|
import type { Db } from '../db';
|
|
3
|
-
import { executeOperation
|
|
3
|
+
import { executeOperation } from '../operations/execute_operation';
|
|
4
4
|
import {
|
|
5
5
|
type CollectionInfo,
|
|
6
6
|
ListCollectionsOperation,
|
|
7
7
|
type ListCollectionsOptions
|
|
8
8
|
} from '../operations/list_collections';
|
|
9
9
|
import type { ClientSession } from '../sessions';
|
|
10
|
-
import { AbstractCursor } from './abstract_cursor';
|
|
10
|
+
import { AbstractCursor, type InitialCursorResponse } from './abstract_cursor';
|
|
11
11
|
|
|
12
12
|
/** @public */
|
|
13
13
|
export class ListCollectionsCursor<
|
|
@@ -34,7 +34,7 @@ export class ListCollectionsCursor<
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
/** @internal */
|
|
37
|
-
async _initialize(session: ClientSession | undefined): Promise<
|
|
37
|
+
async _initialize(session: ClientSession | undefined): Promise<InitialCursorResponse> {
|
|
38
38
|
const operation = new ListCollectionsOperation(this.parent, this.filter, {
|
|
39
39
|
...this.cursorOptions,
|
|
40
40
|
...this.options,
|
|
@@ -43,7 +43,6 @@ export class ListCollectionsCursor<
|
|
|
43
43
|
|
|
44
44
|
const response = await executeOperation(this.parent.client, operation);
|
|
45
45
|
|
|
46
|
-
// TODO: NODE-2882
|
|
47
46
|
return { server: operation.server, session, response };
|
|
48
47
|
}
|
|
49
48
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { Collection } from '../collection';
|
|
2
|
-
import { executeOperation
|
|
2
|
+
import { executeOperation } from '../operations/execute_operation';
|
|
3
3
|
import { ListIndexesOperation, type ListIndexesOptions } from '../operations/indexes';
|
|
4
4
|
import type { ClientSession } from '../sessions';
|
|
5
|
-
import { AbstractCursor } from './abstract_cursor';
|
|
5
|
+
import { AbstractCursor, type InitialCursorResponse } from './abstract_cursor';
|
|
6
6
|
|
|
7
7
|
/** @public */
|
|
8
8
|
export class ListIndexesCursor extends AbstractCursor {
|
|
@@ -23,7 +23,7 @@ export class ListIndexesCursor extends AbstractCursor {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
/** @internal */
|
|
26
|
-
async _initialize(session: ClientSession | undefined): Promise<
|
|
26
|
+
async _initialize(session: ClientSession | undefined): Promise<InitialCursorResponse> {
|
|
27
27
|
const operation = new ListIndexesOperation(this.parent, {
|
|
28
28
|
...this.cursorOptions,
|
|
29
29
|
...this.options,
|
|
@@ -32,7 +32,6 @@ export class ListIndexesCursor extends AbstractCursor {
|
|
|
32
32
|
|
|
33
33
|
const response = await executeOperation(this.parent.client, operation);
|
|
34
34
|
|
|
35
|
-
// TODO: NODE-2882
|
|
36
35
|
return { server: operation.server, session, response };
|
|
37
36
|
}
|
|
38
37
|
}
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import type { BSONSerializeOptions, Document
|
|
1
|
+
import type { BSONSerializeOptions, Document } from '../bson';
|
|
2
|
+
import { CursorResponse } from '../cmap/wire_protocol/responses';
|
|
2
3
|
import type { Db } from '../db';
|
|
3
|
-
import { MongoAPIError
|
|
4
|
-
import { executeOperation
|
|
4
|
+
import { MongoAPIError } from '../error';
|
|
5
|
+
import { executeOperation } from '../operations/execute_operation';
|
|
5
6
|
import { GetMoreOperation } from '../operations/get_more';
|
|
6
7
|
import { RunCommandOperation } from '../operations/run_command';
|
|
7
8
|
import type { ReadConcernLike } from '../read_concern';
|
|
8
9
|
import type { ReadPreferenceLike } from '../read_preference';
|
|
9
10
|
import type { ClientSession } from '../sessions';
|
|
10
11
|
import { ns } from '../utils';
|
|
11
|
-
import { AbstractCursor } from './abstract_cursor';
|
|
12
|
+
import { AbstractCursor, type InitialCursorResponse } from './abstract_cursor';
|
|
12
13
|
|
|
13
14
|
/** @public */
|
|
14
15
|
export type RunCursorCommandOptions = {
|
|
@@ -16,12 +17,6 @@ export type RunCursorCommandOptions = {
|
|
|
16
17
|
session?: ClientSession;
|
|
17
18
|
} & BSONSerializeOptions;
|
|
18
19
|
|
|
19
|
-
/** @internal */
|
|
20
|
-
type RunCursorCommandResponse = {
|
|
21
|
-
cursor: { id: bigint | Long | number; ns: string; firstBatch: Document[] };
|
|
22
|
-
ok: 1;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
20
|
/** @public */
|
|
26
21
|
export class RunCommandCursor extends AbstractCursor {
|
|
27
22
|
public readonly command: Readonly<Record<string, any>>;
|
|
@@ -102,16 +97,16 @@ export class RunCommandCursor extends AbstractCursor {
|
|
|
102
97
|
}
|
|
103
98
|
|
|
104
99
|
/** @internal */
|
|
105
|
-
protected async _initialize(session: ClientSession): Promise<
|
|
106
|
-
const operation = new RunCommandOperation<
|
|
100
|
+
protected async _initialize(session: ClientSession): Promise<InitialCursorResponse> {
|
|
101
|
+
const operation = new RunCommandOperation<CursorResponse>(this.db, this.command, {
|
|
107
102
|
...this.cursorOptions,
|
|
108
103
|
session: session,
|
|
109
|
-
readPreference: this.cursorOptions.readPreference
|
|
104
|
+
readPreference: this.cursorOptions.readPreference,
|
|
105
|
+
responseType: CursorResponse
|
|
110
106
|
});
|
|
107
|
+
|
|
111
108
|
const response = await executeOperation(this.client, operation);
|
|
112
|
-
|
|
113
|
-
throw new MongoUnexpectedServerResponseError('Expected server to respond with cursor');
|
|
114
|
-
}
|
|
109
|
+
|
|
115
110
|
return {
|
|
116
111
|
server: operation.server,
|
|
117
112
|
session,
|
|
@@ -120,13 +115,12 @@ export class RunCommandCursor extends AbstractCursor {
|
|
|
120
115
|
}
|
|
121
116
|
|
|
122
117
|
/** @internal */
|
|
123
|
-
override async getMore(_batchSize: number): Promise<
|
|
118
|
+
override async getMore(_batchSize: number): Promise<CursorResponse> {
|
|
124
119
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
125
120
|
const getMoreOperation = new GetMoreOperation(this.namespace, this.id!, this.server!, {
|
|
126
121
|
...this.cursorOptions,
|
|
127
122
|
session: this.session,
|
|
128
|
-
...this.getMoreOptions
|
|
129
|
-
useCursorResponse: false
|
|
123
|
+
...this.getMoreOptions
|
|
130
124
|
});
|
|
131
125
|
|
|
132
126
|
return await executeOperation(this.client, getMoreOperation);
|