mongodb 6.10.0-dev.20241102.sha.2f3fb466 → 6.10.0-dev.20241107.sha.e5582ed7
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/admin.js +3 -2
- package/lib/admin.js.map +1 -1
- package/lib/beta.d.ts +558 -38
- package/lib/bulk/common.js +4 -4
- package/lib/bulk/common.js.map +1 -1
- package/lib/change_stream.js +111 -51
- package/lib/change_stream.js.map +1 -1
- package/lib/client-side-encryption/auto_encrypter.js +8 -5
- package/lib/client-side-encryption/auto_encrypter.js.map +1 -1
- package/lib/client-side-encryption/client_encryption.js +48 -18
- package/lib/client-side-encryption/client_encryption.js.map +1 -1
- package/lib/client-side-encryption/state_machine.js +43 -29
- package/lib/client-side-encryption/state_machine.js.map +1 -1
- package/lib/cmap/connection.js +78 -6
- package/lib/cmap/connection.js.map +1 -1
- package/lib/cmap/connection_pool.js +14 -9
- package/lib/cmap/connection_pool.js.map +1 -1
- package/lib/cmap/wire_protocol/on_data.js +5 -1
- package/lib/cmap/wire_protocol/on_data.js.map +1 -1
- package/lib/cmap/wire_protocol/responses.js +30 -0
- package/lib/cmap/wire_protocol/responses.js.map +1 -1
- package/lib/collection.js +62 -3
- package/lib/collection.js.map +1 -1
- package/lib/connection_string.js +2 -0
- package/lib/connection_string.js.map +1 -1
- package/lib/cursor/abstract_cursor.js +218 -38
- package/lib/cursor/abstract_cursor.js.map +1 -1
- package/lib/cursor/aggregation_cursor.js +29 -7
- package/lib/cursor/aggregation_cursor.js.map +1 -1
- package/lib/cursor/change_stream_cursor.js +2 -2
- package/lib/cursor/change_stream_cursor.js.map +1 -1
- package/lib/cursor/client_bulk_write_cursor.js +1 -1
- package/lib/cursor/client_bulk_write_cursor.js.map +1 -1
- package/lib/cursor/find_cursor.js +18 -8
- package/lib/cursor/find_cursor.js.map +1 -1
- package/lib/cursor/list_collections_cursor.js +1 -1
- package/lib/cursor/list_collections_cursor.js.map +1 -1
- package/lib/cursor/list_indexes_cursor.js +1 -1
- package/lib/cursor/list_indexes_cursor.js.map +1 -1
- package/lib/cursor/run_command_cursor.js +6 -4
- package/lib/cursor/run_command_cursor.js.map +1 -1
- package/lib/db.js +63 -3
- package/lib/db.js.map +1 -1
- package/lib/error.js +27 -2
- package/lib/error.js.map +1 -1
- package/lib/explain.js +57 -1
- package/lib/explain.js.map +1 -1
- package/lib/gridfs/download.js +31 -3
- package/lib/gridfs/download.js.map +1 -1
- package/lib/gridfs/index.js +49 -14
- package/lib/gridfs/index.js.map +1 -1
- package/lib/gridfs/upload.js +80 -22
- package/lib/gridfs/upload.js.map +1 -1
- package/lib/index.js +9 -5
- package/lib/index.js.map +1 -1
- package/lib/mongo_client.js +70 -1
- package/lib/mongo_client.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 +7 -2
- package/lib/operations/bulk_write.js.map +1 -1
- package/lib/operations/client_bulk_write/client_bulk_write.js +3 -3
- package/lib/operations/client_bulk_write/client_bulk_write.js.map +1 -1
- package/lib/operations/client_bulk_write/executor.js +14 -3
- package/lib/operations/client_bulk_write/executor.js.map +1 -1
- package/lib/operations/command.js +5 -2
- package/lib/operations/command.js.map +1 -1
- package/lib/operations/count.js +2 -2
- package/lib/operations/count.js.map +1 -1
- package/lib/operations/create_collection.js +8 -7
- package/lib/operations/create_collection.js.map +1 -1
- package/lib/operations/delete.js +6 -6
- package/lib/operations/delete.js.map +1 -1
- package/lib/operations/distinct.js +2 -2
- package/lib/operations/distinct.js.map +1 -1
- package/lib/operations/drop.js +8 -8
- package/lib/operations/drop.js.map +1 -1
- package/lib/operations/estimated_document_count.js +2 -2
- package/lib/operations/estimated_document_count.js.map +1 -1
- package/lib/operations/execute_operation.js +16 -10
- package/lib/operations/execute_operation.js.map +1 -1
- package/lib/operations/find.js +6 -3
- package/lib/operations/find.js.map +1 -1
- package/lib/operations/find_and_modify.js +2 -2
- package/lib/operations/find_and_modify.js.map +1 -1
- package/lib/operations/get_more.js +2 -1
- package/lib/operations/get_more.js.map +1 -1
- package/lib/operations/indexes.js +6 -6
- package/lib/operations/indexes.js.map +1 -1
- package/lib/operations/insert.js +6 -6
- package/lib/operations/insert.js.map +1 -1
- package/lib/operations/kill_cursors.js +5 -2
- package/lib/operations/kill_cursors.js.map +1 -1
- package/lib/operations/list_collections.js +2 -2
- package/lib/operations/list_collections.js.map +1 -1
- package/lib/operations/list_databases.js +2 -2
- package/lib/operations/list_databases.js.map +1 -1
- package/lib/operations/operation.js.map +1 -1
- package/lib/operations/profiling_level.js +2 -2
- package/lib/operations/profiling_level.js.map +1 -1
- package/lib/operations/remove_user.js +2 -2
- package/lib/operations/remove_user.js.map +1 -1
- package/lib/operations/rename.js +2 -2
- package/lib/operations/rename.js.map +1 -1
- package/lib/operations/run_command.js +6 -4
- package/lib/operations/run_command.js.map +1 -1
- package/lib/operations/search_indexes/create.js +5 -2
- package/lib/operations/search_indexes/create.js.map +1 -1
- package/lib/operations/search_indexes/drop.js +2 -2
- package/lib/operations/search_indexes/drop.js.map +1 -1
- package/lib/operations/search_indexes/update.js +2 -2
- package/lib/operations/search_indexes/update.js.map +1 -1
- package/lib/operations/set_profiling_level.js +2 -2
- package/lib/operations/set_profiling_level.js.map +1 -1
- package/lib/operations/stats.js +2 -2
- package/lib/operations/stats.js.map +1 -1
- package/lib/operations/update.js +8 -8
- package/lib/operations/update.js.map +1 -1
- package/lib/operations/validate_collection.js +2 -2
- package/lib/operations/validate_collection.js.map +1 -1
- package/lib/sdam/server.js +4 -1
- package/lib/sdam/server.js.map +1 -1
- package/lib/sdam/server_description.js +2 -0
- package/lib/sdam/server_description.js.map +1 -1
- package/lib/sdam/topology.js +38 -11
- package/lib/sdam/topology.js.map +1 -1
- package/lib/sessions.js +145 -74
- package/lib/sessions.js.map +1 -1
- package/lib/timeout.js +217 -16
- package/lib/timeout.js.map +1 -1
- package/lib/utils.js +31 -17
- package/lib/utils.js.map +1 -1
- package/lib/write_concern.js.map +1 -1
- package/mongodb.d.ts +558 -38
- package/package.json +2 -2
- package/src/admin.ts +6 -2
- package/src/bulk/common.ts +17 -5
- package/src/change_stream.ts +127 -52
- package/src/client-side-encryption/auto_encrypter.ts +12 -5
- package/src/client-side-encryption/client_encryption.ts +103 -20
- package/src/client-side-encryption/state_machine.ts +66 -32
- package/src/cmap/connection.ts +105 -8
- package/src/cmap/connection_pool.ts +14 -14
- package/src/cmap/wire_protocol/on_data.ts +11 -1
- package/src/cmap/wire_protocol/responses.ts +35 -1
- package/src/collection.ts +81 -9
- package/src/connection_string.ts +2 -0
- package/src/cursor/abstract_cursor.ts +286 -39
- package/src/cursor/aggregation_cursor.ts +54 -8
- package/src/cursor/change_stream_cursor.ts +6 -2
- package/src/cursor/client_bulk_write_cursor.ts +6 -2
- package/src/cursor/find_cursor.ts +40 -9
- package/src/cursor/list_collections_cursor.ts +1 -1
- package/src/cursor/list_indexes_cursor.ts +1 -1
- package/src/cursor/run_command_cursor.ts +50 -5
- package/src/db.ts +75 -7
- package/src/error.ts +26 -1
- package/src/explain.ts +85 -0
- package/src/gridfs/download.ts +43 -4
- package/src/gridfs/index.ts +64 -16
- package/src/gridfs/upload.ts +152 -45
- package/src/index.ts +26 -4
- package/src/mongo_client.ts +75 -3
- package/src/operations/aggregate.ts +10 -2
- package/src/operations/bulk_write.ts +9 -2
- package/src/operations/client_bulk_write/client_bulk_write.ts +11 -3
- package/src/operations/client_bulk_write/executor.ts +15 -3
- package/src/operations/command.ts +18 -8
- package/src/operations/count.ts +10 -3
- package/src/operations/create_collection.ts +14 -7
- package/src/operations/delete.ts +15 -6
- package/src/operations/distinct.ts +7 -2
- package/src/operations/drop.ts +18 -8
- package/src/operations/estimated_document_count.ts +7 -2
- package/src/operations/execute_operation.ts +22 -13
- package/src/operations/find.ts +17 -5
- package/src/operations/find_and_modify.ts +7 -2
- package/src/operations/get_more.ts +4 -1
- package/src/operations/indexes.ts +20 -7
- package/src/operations/insert.ts +13 -6
- package/src/operations/kill_cursors.ts +10 -2
- package/src/operations/list_collections.ts +10 -1
- package/src/operations/list_databases.ts +9 -2
- package/src/operations/operation.ts +16 -2
- package/src/operations/profiling_level.ts +7 -2
- package/src/operations/remove_user.ts +7 -2
- package/src/operations/rename.ts +7 -2
- package/src/operations/run_command.ts +23 -4
- package/src/operations/search_indexes/create.ts +10 -2
- package/src/operations/search_indexes/drop.ts +7 -2
- package/src/operations/search_indexes/update.ts +7 -2
- package/src/operations/set_profiling_level.ts +4 -2
- package/src/operations/stats.ts +7 -2
- package/src/operations/update.ts +16 -8
- package/src/operations/validate_collection.ts +7 -2
- package/src/sdam/server.ts +14 -4
- package/src/sdam/server_description.ts +4 -0
- package/src/sdam/topology.ts +43 -18
- package/src/sessions.ts +193 -89
- package/src/timeout.ts +310 -23
- package/src/transactions.ts +1 -1
- package/src/utils.ts +42 -28
- package/src/write_concern.ts +6 -3
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import { type Document } from '../bson';
|
|
2
2
|
import { CursorResponse } from '../cmap/wire_protocol/responses';
|
|
3
|
-
import { MongoInvalidArgumentError, MongoTailableCursorError } from '../error';
|
|
4
|
-
import {
|
|
3
|
+
import { MongoAPIError, MongoInvalidArgumentError, MongoTailableCursorError } from '../error';
|
|
4
|
+
import {
|
|
5
|
+
Explain,
|
|
6
|
+
ExplainableCursor,
|
|
7
|
+
type ExplainCommandOptions,
|
|
8
|
+
type ExplainVerbosityLike,
|
|
9
|
+
validateExplainTimeoutOptions
|
|
10
|
+
} from '../explain';
|
|
5
11
|
import type { MongoClient } from '../mongo_client';
|
|
6
12
|
import type { CollationOptions } from '../operations/command';
|
|
7
13
|
import { CountOperation, type CountOptions } from '../operations/count';
|
|
@@ -11,7 +17,7 @@ import type { Hint } from '../operations/operation';
|
|
|
11
17
|
import type { ClientSession } from '../sessions';
|
|
12
18
|
import { formatSort, type Sort, type SortDirection } from '../sort';
|
|
13
19
|
import { emitWarningOnce, mergeOptions, type MongoDBNamespace, squashError } from '../utils';
|
|
14
|
-
import {
|
|
20
|
+
import { type InitialCursorResponse } from './abstract_cursor';
|
|
15
21
|
|
|
16
22
|
/** @public Flags allowed for cursor */
|
|
17
23
|
export const FLAGS = [
|
|
@@ -24,7 +30,7 @@ export const FLAGS = [
|
|
|
24
30
|
] as const;
|
|
25
31
|
|
|
26
32
|
/** @public */
|
|
27
|
-
export class FindCursor<TSchema = any> extends
|
|
33
|
+
export class FindCursor<TSchema = any> extends ExplainableCursor<TSchema> {
|
|
28
34
|
/** @internal */
|
|
29
35
|
private cursorFilter: Document;
|
|
30
36
|
/** @internal */
|
|
@@ -63,13 +69,25 @@ export class FindCursor<TSchema = any> extends AbstractCursor<TSchema> {
|
|
|
63
69
|
|
|
64
70
|
/** @internal */
|
|
65
71
|
async _initialize(session: ClientSession): Promise<InitialCursorResponse> {
|
|
66
|
-
const
|
|
72
|
+
const options = {
|
|
67
73
|
...this.findOptions, // NOTE: order matters here, we may need to refine this
|
|
68
74
|
...this.cursorOptions,
|
|
69
75
|
session
|
|
70
|
-
}
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
if (options.explain) {
|
|
79
|
+
try {
|
|
80
|
+
validateExplainTimeoutOptions(options, Explain.fromOptions(options));
|
|
81
|
+
} catch {
|
|
82
|
+
throw new MongoAPIError(
|
|
83
|
+
'timeoutMS cannot be used with explain when explain is specified in findOptions'
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
71
87
|
|
|
72
|
-
const
|
|
88
|
+
const findOperation = new FindOperation(this.namespace, this.cursorFilter, options);
|
|
89
|
+
|
|
90
|
+
const response = await executeOperation(this.client, findOperation, this.timeoutContext);
|
|
73
91
|
|
|
74
92
|
// the response is not a cursor when `explain` is enabled
|
|
75
93
|
this.numReturned = response.batchSize;
|
|
@@ -133,14 +151,27 @@ export class FindCursor<TSchema = any> extends AbstractCursor<TSchema> {
|
|
|
133
151
|
}
|
|
134
152
|
|
|
135
153
|
/** Execute the explain for the cursor */
|
|
136
|
-
async explain(
|
|
154
|
+
async explain(): Promise<Document>;
|
|
155
|
+
async explain(verbosity: ExplainVerbosityLike | ExplainCommandOptions): Promise<Document>;
|
|
156
|
+
async explain(options: { timeoutMS?: number }): Promise<Document>;
|
|
157
|
+
async explain(
|
|
158
|
+
verbosity: ExplainVerbosityLike | ExplainCommandOptions,
|
|
159
|
+
options: { timeoutMS?: number }
|
|
160
|
+
): Promise<Document>;
|
|
161
|
+
async explain(
|
|
162
|
+
verbosity?: ExplainVerbosityLike | ExplainCommandOptions | { timeoutMS?: number },
|
|
163
|
+
options?: { timeoutMS?: number }
|
|
164
|
+
): Promise<Document> {
|
|
165
|
+
const { explain, timeout } = this.resolveExplainTimeoutOptions(verbosity, options);
|
|
166
|
+
|
|
137
167
|
return (
|
|
138
168
|
await executeOperation(
|
|
139
169
|
this.client,
|
|
140
170
|
new FindOperation(this.namespace, this.cursorFilter, {
|
|
141
171
|
...this.findOptions, // NOTE: order matters here, we may need to refine this
|
|
142
172
|
...this.cursorOptions,
|
|
143
|
-
|
|
173
|
+
...timeout,
|
|
174
|
+
explain: explain ?? true
|
|
144
175
|
})
|
|
145
176
|
)
|
|
146
177
|
).shift(this.deserializationOptions);
|
|
@@ -41,7 +41,7 @@ export class ListCollectionsCursor<
|
|
|
41
41
|
session
|
|
42
42
|
});
|
|
43
43
|
|
|
44
|
-
const response = await executeOperation(this.parent.client, operation);
|
|
44
|
+
const response = await executeOperation(this.parent.client, operation, this.timeoutContext);
|
|
45
45
|
|
|
46
46
|
return { server: operation.server, session, response };
|
|
47
47
|
}
|
|
@@ -30,7 +30,7 @@ export class ListIndexesCursor extends AbstractCursor {
|
|
|
30
30
|
session
|
|
31
31
|
});
|
|
32
32
|
|
|
33
|
-
const response = await executeOperation(this.parent.client, operation);
|
|
33
|
+
const response = await executeOperation(this.parent.client, operation, this.timeoutContext);
|
|
34
34
|
|
|
35
35
|
return { server: operation.server, session, response };
|
|
36
36
|
}
|
|
@@ -9,12 +9,55 @@ import type { ReadConcernLike } from '../read_concern';
|
|
|
9
9
|
import type { ReadPreferenceLike } from '../read_preference';
|
|
10
10
|
import type { ClientSession } from '../sessions';
|
|
11
11
|
import { ns } from '../utils';
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
AbstractCursor,
|
|
14
|
+
type CursorTimeoutMode,
|
|
15
|
+
type InitialCursorResponse
|
|
16
|
+
} from './abstract_cursor';
|
|
13
17
|
|
|
14
18
|
/** @public */
|
|
15
19
|
export type RunCursorCommandOptions = {
|
|
16
20
|
readPreference?: ReadPreferenceLike;
|
|
17
21
|
session?: ClientSession;
|
|
22
|
+
/**
|
|
23
|
+
* @experimental
|
|
24
|
+
* Specifies the time an operation will run until it throws a timeout error. Note that if
|
|
25
|
+
* `maxTimeMS` is provided in the command in addition to setting `timeoutMS` in the options, then
|
|
26
|
+
* the original value of `maxTimeMS` will be overwritten.
|
|
27
|
+
*/
|
|
28
|
+
timeoutMS?: number;
|
|
29
|
+
/**
|
|
30
|
+
* @public
|
|
31
|
+
* @experimental
|
|
32
|
+
* Specifies how `timeoutMS` is applied to the cursor. Can be either `'cursorLifeTime'` or `'iteration'`
|
|
33
|
+
* When set to `'iteration'`, the deadline specified by `timeoutMS` applies to each call of
|
|
34
|
+
* `cursor.next()`.
|
|
35
|
+
* When set to `'cursorLifetime'`, the deadline applies to the life of the entire cursor.
|
|
36
|
+
*
|
|
37
|
+
* Depending on the type of cursor being used, this option has different default values.
|
|
38
|
+
* For non-tailable cursors, this value defaults to `'cursorLifetime'`
|
|
39
|
+
* For tailable cursors, this value defaults to `'iteration'` since tailable cursors, by
|
|
40
|
+
* definition can have an arbitrarily long lifetime.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```ts
|
|
44
|
+
* const cursor = collection.find({}, {timeoutMS: 100, timeoutMode: 'iteration'});
|
|
45
|
+
* for await (const doc of cursor) {
|
|
46
|
+
* // process doc
|
|
47
|
+
* // This will throw a timeout error if any of the iterator's `next()` calls takes more than 100ms, but
|
|
48
|
+
* // will continue to iterate successfully otherwise, regardless of the number of batches.
|
|
49
|
+
* }
|
|
50
|
+
* ```
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```ts
|
|
54
|
+
* const cursor = collection.find({}, { timeoutMS: 1000, timeoutMode: 'cursorLifetime' });
|
|
55
|
+
* const docs = await cursor.toArray(); // This entire line will throw a timeout error if all batches are not fetched and returned within 1000ms.
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
timeoutMode?: CursorTimeoutMode;
|
|
59
|
+
tailable?: boolean;
|
|
60
|
+
awaitData?: boolean;
|
|
18
61
|
} & BSONSerializeOptions;
|
|
19
62
|
|
|
20
63
|
/** @public */
|
|
@@ -46,7 +89,7 @@ export class RunCommandCursor extends AbstractCursor {
|
|
|
46
89
|
|
|
47
90
|
/**
|
|
48
91
|
* Controls the `getMore.batchSize` field
|
|
49
|
-
* @param
|
|
92
|
+
* @param batchSize - the number documents to return in the `nextBatch`
|
|
50
93
|
*/
|
|
51
94
|
public setBatchSize(batchSize: number): this {
|
|
52
95
|
this.getMoreOptions.batchSize = batchSize;
|
|
@@ -72,7 +115,9 @@ export class RunCommandCursor extends AbstractCursor {
|
|
|
72
115
|
);
|
|
73
116
|
}
|
|
74
117
|
|
|
75
|
-
/**
|
|
118
|
+
/**
|
|
119
|
+
* Unsupported for RunCommandCursor: maxTimeMS must be configured directly on command document
|
|
120
|
+
*/
|
|
76
121
|
public override maxTimeMS(_: number): never {
|
|
77
122
|
throw new MongoAPIError(
|
|
78
123
|
'maxTimeMS must be configured on the command document directly, to configure getMore.maxTimeMS use cursor.setMaxTimeMS()'
|
|
@@ -105,7 +150,7 @@ export class RunCommandCursor extends AbstractCursor {
|
|
|
105
150
|
responseType: CursorResponse
|
|
106
151
|
});
|
|
107
152
|
|
|
108
|
-
const response = await executeOperation(this.client, operation);
|
|
153
|
+
const response = await executeOperation(this.client, operation, this.timeoutContext);
|
|
109
154
|
|
|
110
155
|
return {
|
|
111
156
|
server: operation.server,
|
|
@@ -123,6 +168,6 @@ export class RunCommandCursor extends AbstractCursor {
|
|
|
123
168
|
...this.getMoreOptions
|
|
124
169
|
});
|
|
125
170
|
|
|
126
|
-
return await executeOperation(this.client, getMoreOperation);
|
|
171
|
+
return await executeOperation(this.client, getMoreOperation, this.timeoutContext);
|
|
127
172
|
}
|
|
128
173
|
}
|
package/src/db.ts
CHANGED
|
@@ -97,7 +97,10 @@ export interface DbOptions extends BSONSerializeOptions, WriteConcernOptions {
|
|
|
97
97
|
readConcern?: ReadConcern;
|
|
98
98
|
/** Should retry failed writes */
|
|
99
99
|
retryWrites?: boolean;
|
|
100
|
-
/**
|
|
100
|
+
/**
|
|
101
|
+
* @experimental
|
|
102
|
+
* Specifies the time an operation will run until it throws a timeout error
|
|
103
|
+
*/
|
|
101
104
|
timeoutMS?: number;
|
|
102
105
|
}
|
|
103
106
|
|
|
@@ -222,6 +225,10 @@ export class Db {
|
|
|
222
225
|
return this.s.namespace.toString();
|
|
223
226
|
}
|
|
224
227
|
|
|
228
|
+
public get timeoutMS(): number | undefined {
|
|
229
|
+
return this.s.options?.timeoutMS;
|
|
230
|
+
}
|
|
231
|
+
|
|
225
232
|
/**
|
|
226
233
|
* Create a new collection on a server with the specified options. Use this to create capped collections.
|
|
227
234
|
* More information about command options available at https://www.mongodb.com/docs/manual/reference/command/create/
|
|
@@ -270,11 +277,16 @@ export class Db {
|
|
|
270
277
|
// Intentionally, we do not inherit options from parent for this operation.
|
|
271
278
|
return await executeOperation(
|
|
272
279
|
this.client,
|
|
273
|
-
new RunCommandOperation(
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
280
|
+
new RunCommandOperation(
|
|
281
|
+
this,
|
|
282
|
+
command,
|
|
283
|
+
resolveOptions(undefined, {
|
|
284
|
+
...resolveBSONOptions(options),
|
|
285
|
+
timeoutMS: options?.timeoutMS ?? this.timeoutMS,
|
|
286
|
+
session: options?.session,
|
|
287
|
+
readPreference: options?.readPreference
|
|
288
|
+
})
|
|
289
|
+
)
|
|
278
290
|
);
|
|
279
291
|
}
|
|
280
292
|
|
|
@@ -379,7 +391,11 @@ export class Db {
|
|
|
379
391
|
new RenameOperation(
|
|
380
392
|
this.collection<TSchema>(fromCollection) as TODO_NODE_3286,
|
|
381
393
|
toCollection,
|
|
382
|
-
|
|
394
|
+
resolveOptions(undefined, {
|
|
395
|
+
...options,
|
|
396
|
+
new_collection: true,
|
|
397
|
+
readPreference: ReadPreference.primary
|
|
398
|
+
})
|
|
383
399
|
) as TODO_NODE_3286
|
|
384
400
|
);
|
|
385
401
|
}
|
|
@@ -517,6 +533,58 @@ export class Db {
|
|
|
517
533
|
* - The first is to provide the schema that may be defined for all the collections within this database
|
|
518
534
|
* - The second is to override the shape of the change stream document entirely, if it is not provided the type will default to ChangeStreamDocument of the first argument
|
|
519
535
|
*
|
|
536
|
+
* @remarks
|
|
537
|
+
* When `timeoutMS` is configured for a change stream, it will have different behaviour depending
|
|
538
|
+
* on whether the change stream is in iterator mode or emitter mode. In both cases, a change
|
|
539
|
+
* stream will time out if it does not receive a change event within `timeoutMS` of the last change
|
|
540
|
+
* event.
|
|
541
|
+
*
|
|
542
|
+
* Note that if a change stream is consistently timing out when watching a collection, database or
|
|
543
|
+
* client that is being changed, then this may be due to the server timing out before it can finish
|
|
544
|
+
* processing the existing oplog. To address this, restart the change stream with a higher
|
|
545
|
+
* `timeoutMS`.
|
|
546
|
+
*
|
|
547
|
+
* If the change stream times out the initial aggregate operation to establish the change stream on
|
|
548
|
+
* the server, then the client will close the change stream. If the getMore calls to the server
|
|
549
|
+
* time out, then the change stream will be left open, but will throw a MongoOperationTimeoutError
|
|
550
|
+
* when in iterator mode and emit an error event that returns a MongoOperationTimeoutError in
|
|
551
|
+
* emitter mode.
|
|
552
|
+
*
|
|
553
|
+
* To determine whether or not the change stream is still open following a timeout, check the
|
|
554
|
+
* {@link ChangeStream.closed} getter.
|
|
555
|
+
*
|
|
556
|
+
* @example
|
|
557
|
+
* In iterator mode, if a next() call throws a timeout error, it will attempt to resume the change stream.
|
|
558
|
+
* The next call can just be retried after this succeeds.
|
|
559
|
+
* ```ts
|
|
560
|
+
* const changeStream = collection.watch([], { timeoutMS: 100 });
|
|
561
|
+
* try {
|
|
562
|
+
* await changeStream.next();
|
|
563
|
+
* } catch (e) {
|
|
564
|
+
* if (e instanceof MongoOperationTimeoutError && !changeStream.closed) {
|
|
565
|
+
* await changeStream.next();
|
|
566
|
+
* }
|
|
567
|
+
* throw e;
|
|
568
|
+
* }
|
|
569
|
+
* ```
|
|
570
|
+
*
|
|
571
|
+
* @example
|
|
572
|
+
* In emitter mode, if the change stream goes `timeoutMS` without emitting a change event, it will
|
|
573
|
+
* emit an error event that returns a MongoOperationTimeoutError, but will not close the change
|
|
574
|
+
* stream unless the resume attempt fails. There is no need to re-establish change listeners as
|
|
575
|
+
* this will automatically continue emitting change events once the resume attempt completes.
|
|
576
|
+
*
|
|
577
|
+
* ```ts
|
|
578
|
+
* const changeStream = collection.watch([], { timeoutMS: 100 });
|
|
579
|
+
* changeStream.on('change', console.log);
|
|
580
|
+
* changeStream.on('error', e => {
|
|
581
|
+
* if (e instanceof MongoOperationTimeoutError && !changeStream.closed) {
|
|
582
|
+
* // do nothing
|
|
583
|
+
* } else {
|
|
584
|
+
* changeStream.close();
|
|
585
|
+
* }
|
|
586
|
+
* });
|
|
587
|
+
* ```
|
|
520
588
|
* @param pipeline - An array of {@link https://www.mongodb.com/docs/manual/reference/operator/aggregation-pipeline/|aggregation pipeline stages} through which to pass change stream documents. This allows for filtering (using $match) and manipulating the change stream documents.
|
|
521
589
|
* @param options - Optional settings for the command
|
|
522
590
|
* @typeParam TSchema - Type of the data being detected by the change stream
|
package/src/error.ts
CHANGED
|
@@ -311,7 +311,7 @@ export class MongoAPIError extends MongoDriverError {
|
|
|
311
311
|
|
|
312
312
|
/**
|
|
313
313
|
* An error generated when the driver encounters unexpected input
|
|
314
|
-
* or reaches an unexpected/invalid internal state
|
|
314
|
+
* or reaches an unexpected/invalid internal state.
|
|
315
315
|
*
|
|
316
316
|
* @privateRemarks
|
|
317
317
|
* Should **never** be directly instantiated.
|
|
@@ -857,6 +857,31 @@ export class MongoUnexpectedServerResponseError extends MongoRuntimeError {
|
|
|
857
857
|
}
|
|
858
858
|
}
|
|
859
859
|
|
|
860
|
+
/**
|
|
861
|
+
* @public
|
|
862
|
+
* @category Error
|
|
863
|
+
*
|
|
864
|
+
* The `MongoOperationTimeoutError` class represents an error that occurs when an operation could not be completed within the specified `timeoutMS`.
|
|
865
|
+
* It is generated by the driver in support of the "client side operation timeout" feature so inherits from `MongoDriverError`.
|
|
866
|
+
* When `timeoutMS` is enabled `MongoServerError`s relating to `MaxTimeExpired` errors will be converted to `MongoOperationTimeoutError`
|
|
867
|
+
*
|
|
868
|
+
* @example
|
|
869
|
+
* ```ts
|
|
870
|
+
* try {
|
|
871
|
+
* await blogs.insertOne(blogPost, { timeoutMS: 60_000 })
|
|
872
|
+
* } catch (error) {
|
|
873
|
+
* if (error instanceof MongoOperationTimeoutError) {
|
|
874
|
+
* console.log(`Oh no! writer's block!`, error);
|
|
875
|
+
* }
|
|
876
|
+
* }
|
|
877
|
+
* ```
|
|
878
|
+
*/
|
|
879
|
+
export class MongoOperationTimeoutError extends MongoDriverError {
|
|
880
|
+
override get name(): string {
|
|
881
|
+
return 'MongoOperationTimeoutError';
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
|
|
860
885
|
/**
|
|
861
886
|
* An error thrown when the user attempts to add options to a cursor that has already been
|
|
862
887
|
* initialized
|
package/src/explain.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import { type Document } from './bson';
|
|
2
|
+
import { AbstractCursor } from './cursor/abstract_cursor';
|
|
3
|
+
import { MongoAPIError } from './error';
|
|
4
|
+
|
|
1
5
|
/** @public */
|
|
2
6
|
export const ExplainVerbosity = Object.freeze({
|
|
3
7
|
queryPlanner: 'queryPlanner',
|
|
@@ -86,3 +90,84 @@ export class Explain {
|
|
|
86
90
|
return new Explain(verbosity, maxTimeMS);
|
|
87
91
|
}
|
|
88
92
|
}
|
|
93
|
+
|
|
94
|
+
export function validateExplainTimeoutOptions(options: Document, explain?: Explain) {
|
|
95
|
+
const { maxTimeMS, timeoutMS } = options;
|
|
96
|
+
if (timeoutMS != null && (maxTimeMS != null || explain?.maxTimeMS != null)) {
|
|
97
|
+
throw new MongoAPIError('Cannot use maxTimeMS with timeoutMS for explain commands.');
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Applies an explain to a given command.
|
|
103
|
+
* @internal
|
|
104
|
+
*
|
|
105
|
+
* @param command - the command on which to apply the explain
|
|
106
|
+
* @param options - the options containing the explain verbosity
|
|
107
|
+
*/
|
|
108
|
+
export function decorateWithExplain(
|
|
109
|
+
command: Document,
|
|
110
|
+
explain: Explain
|
|
111
|
+
): {
|
|
112
|
+
explain: Document;
|
|
113
|
+
verbosity: ExplainVerbosity;
|
|
114
|
+
maxTimeMS?: number;
|
|
115
|
+
} {
|
|
116
|
+
type ExplainCommand = ReturnType<typeof decorateWithExplain>;
|
|
117
|
+
const { verbosity, maxTimeMS } = explain;
|
|
118
|
+
const baseCommand: ExplainCommand = { explain: command, verbosity };
|
|
119
|
+
|
|
120
|
+
if (typeof maxTimeMS === 'number') {
|
|
121
|
+
baseCommand.maxTimeMS = maxTimeMS;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return baseCommand;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* @public
|
|
129
|
+
*
|
|
130
|
+
* A base class for any cursors that have `explain()` methods.
|
|
131
|
+
*/
|
|
132
|
+
export abstract class ExplainableCursor<TSchema> extends AbstractCursor<TSchema> {
|
|
133
|
+
/** Execute the explain for the cursor */
|
|
134
|
+
abstract explain(): Promise<Document>;
|
|
135
|
+
abstract explain(verbosity: ExplainVerbosityLike | ExplainCommandOptions): Promise<Document>;
|
|
136
|
+
abstract explain(options: { timeoutMS?: number }): Promise<Document>;
|
|
137
|
+
abstract explain(
|
|
138
|
+
verbosity: ExplainVerbosityLike | ExplainCommandOptions,
|
|
139
|
+
options: { timeoutMS?: number }
|
|
140
|
+
): Promise<Document>;
|
|
141
|
+
abstract explain(
|
|
142
|
+
verbosity?: ExplainVerbosityLike | ExplainCommandOptions | { timeoutMS?: number },
|
|
143
|
+
options?: { timeoutMS?: number }
|
|
144
|
+
): Promise<Document>;
|
|
145
|
+
|
|
146
|
+
protected resolveExplainTimeoutOptions(
|
|
147
|
+
verbosity?: ExplainVerbosityLike | ExplainCommandOptions | { timeoutMS?: number },
|
|
148
|
+
options?: { timeoutMS?: number }
|
|
149
|
+
): { timeout?: { timeoutMS?: number }; explain?: ExplainVerbosityLike | ExplainCommandOptions } {
|
|
150
|
+
let explain: ExplainVerbosityLike | ExplainCommandOptions | undefined;
|
|
151
|
+
let timeout: { timeoutMS?: number } | undefined;
|
|
152
|
+
|
|
153
|
+
if (verbosity == null && options == null) {
|
|
154
|
+
explain = undefined;
|
|
155
|
+
timeout = undefined;
|
|
156
|
+
} else if (verbosity != null && options == null) {
|
|
157
|
+
explain =
|
|
158
|
+
typeof verbosity !== 'object'
|
|
159
|
+
? verbosity
|
|
160
|
+
: 'verbosity' in verbosity
|
|
161
|
+
? verbosity
|
|
162
|
+
: undefined;
|
|
163
|
+
|
|
164
|
+
timeout = typeof verbosity === 'object' && 'timeoutMS' in verbosity ? verbosity : undefined;
|
|
165
|
+
} else {
|
|
166
|
+
// @ts-expect-error TS isn't smart enough to determine that if both options are provided, the first is explain options
|
|
167
|
+
explain = verbosity;
|
|
168
|
+
timeout = options;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return { timeout, explain };
|
|
172
|
+
}
|
|
173
|
+
}
|
package/src/gridfs/download.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { Readable } from 'stream';
|
|
|
2
2
|
|
|
3
3
|
import type { Document, ObjectId } from '../bson';
|
|
4
4
|
import type { Collection } from '../collection';
|
|
5
|
+
import { CursorTimeoutMode } from '../cursor/abstract_cursor';
|
|
5
6
|
import type { FindCursor } from '../cursor/find_cursor';
|
|
6
7
|
import {
|
|
7
8
|
MongoGridFSChunkError,
|
|
@@ -12,6 +13,7 @@ import {
|
|
|
12
13
|
import type { FindOptions } from '../operations/find';
|
|
13
14
|
import type { ReadPreference } from '../read_preference';
|
|
14
15
|
import type { Sort } from '../sort';
|
|
16
|
+
import { CSOTTimeoutContext } from '../timeout';
|
|
15
17
|
import type { Callback } from '../utils';
|
|
16
18
|
import type { GridFSChunk } from './upload';
|
|
17
19
|
|
|
@@ -28,7 +30,10 @@ export interface GridFSBucketReadStreamOptions {
|
|
|
28
30
|
* to be returned by the stream. `end` is non-inclusive
|
|
29
31
|
*/
|
|
30
32
|
end?: number;
|
|
31
|
-
/**
|
|
33
|
+
/**
|
|
34
|
+
* @experimental
|
|
35
|
+
* Specifies the time an operation will run until it throws a timeout error
|
|
36
|
+
*/
|
|
32
37
|
timeoutMS?: number;
|
|
33
38
|
}
|
|
34
39
|
|
|
@@ -98,8 +103,10 @@ export interface GridFSBucketReadStreamPrivate {
|
|
|
98
103
|
skip?: number;
|
|
99
104
|
start: number;
|
|
100
105
|
end: number;
|
|
106
|
+
timeoutMS?: number;
|
|
101
107
|
};
|
|
102
108
|
readPreference?: ReadPreference;
|
|
109
|
+
timeoutContext?: CSOTTimeoutContext;
|
|
103
110
|
}
|
|
104
111
|
|
|
105
112
|
/**
|
|
@@ -148,7 +155,11 @@ export class GridFSBucketReadStream extends Readable {
|
|
|
148
155
|
end: 0,
|
|
149
156
|
...options
|
|
150
157
|
},
|
|
151
|
-
readPreference
|
|
158
|
+
readPreference,
|
|
159
|
+
timeoutContext:
|
|
160
|
+
options?.timeoutMS != null
|
|
161
|
+
? new CSOTTimeoutContext({ timeoutMS: options.timeoutMS, serverSelectionTimeoutMS: 0 })
|
|
162
|
+
: undefined
|
|
152
163
|
};
|
|
153
164
|
}
|
|
154
165
|
|
|
@@ -196,7 +207,8 @@ export class GridFSBucketReadStream extends Readable {
|
|
|
196
207
|
async abort(): Promise<void> {
|
|
197
208
|
this.push(null);
|
|
198
209
|
this.destroy();
|
|
199
|
-
|
|
210
|
+
const remainingTimeMS = this.s.timeoutContext?.getRemainingTimeMSOrThrow();
|
|
211
|
+
await this.s.cursor?.close({ timeoutMS: remainingTimeMS });
|
|
200
212
|
}
|
|
201
213
|
}
|
|
202
214
|
|
|
@@ -352,7 +364,22 @@ function init(stream: GridFSBucketReadStream): void {
|
|
|
352
364
|
filter['n'] = { $gte: skip };
|
|
353
365
|
}
|
|
354
366
|
}
|
|
355
|
-
|
|
367
|
+
|
|
368
|
+
let remainingTimeMS: number | undefined;
|
|
369
|
+
try {
|
|
370
|
+
remainingTimeMS = stream.s.timeoutContext?.getRemainingTimeMSOrThrow(
|
|
371
|
+
`Download timed out after ${stream.s.timeoutContext?.timeoutMS}ms`
|
|
372
|
+
);
|
|
373
|
+
} catch (error) {
|
|
374
|
+
return stream.destroy(error);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
stream.s.cursor = stream.s.chunks
|
|
378
|
+
.find(filter, {
|
|
379
|
+
timeoutMode: stream.s.options.timeoutMS != null ? CursorTimeoutMode.LIFETIME : undefined,
|
|
380
|
+
timeoutMS: remainingTimeMS
|
|
381
|
+
})
|
|
382
|
+
.sort({ n: 1 });
|
|
356
383
|
|
|
357
384
|
if (stream.s.readPreference) {
|
|
358
385
|
stream.s.cursor.withReadPreference(stream.s.readPreference);
|
|
@@ -371,6 +398,18 @@ function init(stream: GridFSBucketReadStream): void {
|
|
|
371
398
|
return;
|
|
372
399
|
};
|
|
373
400
|
|
|
401
|
+
let remainingTimeMS: number | undefined;
|
|
402
|
+
try {
|
|
403
|
+
remainingTimeMS = stream.s.timeoutContext?.getRemainingTimeMSOrThrow(
|
|
404
|
+
`Download timed out after ${stream.s.timeoutContext?.timeoutMS}ms`
|
|
405
|
+
);
|
|
406
|
+
} catch (error) {
|
|
407
|
+
if (!stream.destroyed) stream.destroy(error);
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
findOneOptions.timeoutMS = remainingTimeMS;
|
|
412
|
+
|
|
374
413
|
stream.s.files.findOne(stream.s.filter, findOneOptions).then(handleReadResult, error => {
|
|
375
414
|
if (stream.destroyed) return;
|
|
376
415
|
stream.destroy(error);
|