mongodb 6.10.0 → 6.11.0-dev.20241123.sha.32f7ac63
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/README.md +2 -0
- package/lib/admin.js +3 -2
- package/lib/admin.js.map +1 -1
- package/lib/beta.d.ts +562 -45
- 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/auth/mongo_credentials.js +5 -2
- package/lib/cmap/auth/mongo_credentials.js.map +1 -1
- package/lib/cmap/auth/mongodb_aws.js +1 -1
- package/lib/cmap/auth/mongodb_aws.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc/k8s_machine_workflow.js +38 -0
- package/lib/cmap/auth/mongodb_oidc/k8s_machine_workflow.js.map +1 -0
- package/lib/cmap/auth/mongodb_oidc.js +2 -0
- package/lib/cmap/auth/mongodb_oidc.js.map +1 -1
- package/lib/cmap/connect.js +13 -1
- package/lib/cmap/connect.js.map +1 -1
- package/lib/cmap/connection.js +75 -17
- package/lib/cmap/connection.js.map +1 -1
- package/lib/cmap/connection_pool.js +14 -12
- 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 +221 -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 +34 -9
- 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/read_concern.js +1 -1
- package/lib/sdam/common.js +0 -7
- package/lib/sdam/common.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 +4 -2
- package/lib/sdam/server_description.js.map +1 -1
- package/lib/sdam/server_selection.js +5 -2
- package/lib/sdam/server_selection.js.map +1 -1
- package/lib/sdam/topology.js +38 -15
- package/lib/sdam/topology.js.map +1 -1
- package/lib/sessions.js +157 -98
- package/lib/sessions.js.map +1 -1
- package/lib/timeout.js +231 -16
- package/lib/timeout.js.map +1 -1
- package/lib/utils.js +36 -19
- package/lib/utils.js.map +1 -1
- package/lib/write_concern.js.map +1 -1
- package/mongodb.d.ts +562 -45
- package/package.json +18 -17
- 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/auth/mongo_credentials.ts +6 -3
- package/src/cmap/auth/mongodb_aws.ts +1 -1
- package/src/cmap/auth/mongodb_oidc/k8s_machine_workflow.ts +38 -0
- package/src/cmap/auth/mongodb_oidc.ts +3 -1
- package/src/cmap/connect.ts +18 -1
- package/src/cmap/connection.ts +105 -17
- package/src/cmap/connection_pool.ts +15 -17
- package/src/cmap/handshake/client_metadata.ts +1 -1
- 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 +287 -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 +33 -8
- 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 +153 -45
- package/src/index.ts +27 -5
- package/src/mongo_client.ts +76 -4
- 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/read_concern.ts +1 -1
- package/src/sdam/common.ts +0 -11
- package/src/sdam/server.ts +14 -4
- package/src/sdam/server_description.ts +6 -2
- package/src/sdam/server_selection.ts +5 -2
- package/src/sdam/topology.ts +43 -27
- package/src/sessions.ts +206 -120
- package/src/timeout.ts +327 -23
- package/src/transactions.ts +1 -1
- package/src/utils.ts +47 -30
- package/src/write_concern.ts +6 -3
package/src/timeout.ts
CHANGED
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
import { clearTimeout, setTimeout } from 'timers';
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { type Document } from './bson';
|
|
4
|
+
import { MongoInvalidArgumentError, MongoOperationTimeoutError, MongoRuntimeError } from './error';
|
|
5
|
+
import { type ClientSession } from './sessions';
|
|
6
|
+
import { csotMin, noop } from './utils';
|
|
5
7
|
|
|
6
8
|
/** @internal */
|
|
7
9
|
export class TimeoutError extends Error {
|
|
10
|
+
duration: number;
|
|
8
11
|
override get name(): 'TimeoutError' {
|
|
9
12
|
return 'TimeoutError';
|
|
10
13
|
}
|
|
11
14
|
|
|
12
|
-
constructor(message: string, options
|
|
15
|
+
constructor(message: string, options: { cause?: Error; duration: number }) {
|
|
13
16
|
super(message, options);
|
|
17
|
+
this.duration = options.duration;
|
|
14
18
|
}
|
|
15
19
|
|
|
16
20
|
static is(error: unknown): error is TimeoutError {
|
|
@@ -29,25 +33,38 @@ type Reject = Parameters<ConstructorParameters<typeof Promise<never>>[0]>[1];
|
|
|
29
33
|
* if interacted with exclusively through its public API
|
|
30
34
|
* */
|
|
31
35
|
export class Timeout extends Promise<never> {
|
|
32
|
-
get [Symbol.toStringTag](): 'MongoDBTimeout' {
|
|
33
|
-
return 'MongoDBTimeout';
|
|
34
|
-
}
|
|
35
|
-
|
|
36
36
|
private id?: NodeJS.Timeout;
|
|
37
37
|
|
|
38
38
|
public readonly start: number;
|
|
39
39
|
public ended: number | null = null;
|
|
40
40
|
public duration: number;
|
|
41
|
-
|
|
41
|
+
private timedOut = false;
|
|
42
|
+
public cleared = false;
|
|
43
|
+
|
|
44
|
+
get remainingTime(): number {
|
|
45
|
+
if (this.timedOut) return 0;
|
|
46
|
+
if (this.duration === 0) return Infinity;
|
|
47
|
+
return this.start + this.duration - Math.trunc(performance.now());
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
get timeElapsed(): number {
|
|
51
|
+
return Math.trunc(performance.now()) - this.start;
|
|
52
|
+
}
|
|
42
53
|
|
|
43
54
|
/** Create a new timeout that expires in `duration` ms */
|
|
44
|
-
private constructor(
|
|
45
|
-
|
|
55
|
+
private constructor(
|
|
56
|
+
executor: Executor = () => null,
|
|
57
|
+
options?: { duration: number; unref?: true; rejection?: Error }
|
|
58
|
+
) {
|
|
59
|
+
const duration = options?.duration ?? 0;
|
|
60
|
+
const unref = !!options?.unref;
|
|
61
|
+
const rejection = options?.rejection;
|
|
46
62
|
|
|
47
63
|
if (duration < 0) {
|
|
48
64
|
throw new MongoInvalidArgumentError('Cannot create a Timeout with a negative duration');
|
|
49
65
|
}
|
|
50
66
|
|
|
67
|
+
let reject!: Reject;
|
|
51
68
|
super((_, promiseReject) => {
|
|
52
69
|
reject = promiseReject;
|
|
53
70
|
|
|
@@ -57,16 +74,20 @@ export class Timeout extends Promise<never> {
|
|
|
57
74
|
this.duration = duration;
|
|
58
75
|
this.start = Math.trunc(performance.now());
|
|
59
76
|
|
|
60
|
-
if (this.duration > 0) {
|
|
77
|
+
if (rejection == null && this.duration > 0) {
|
|
61
78
|
this.id = setTimeout(() => {
|
|
62
79
|
this.ended = Math.trunc(performance.now());
|
|
63
80
|
this.timedOut = true;
|
|
64
|
-
reject(new TimeoutError(`Expired after ${duration}ms
|
|
81
|
+
reject(new TimeoutError(`Expired after ${duration}ms`, { duration }));
|
|
65
82
|
}, this.duration);
|
|
66
83
|
if (typeof this.id.unref === 'function' && unref) {
|
|
67
84
|
// Ensure we do not keep the Node.js event loop running
|
|
68
85
|
this.id.unref();
|
|
69
86
|
}
|
|
87
|
+
} else if (rejection != null) {
|
|
88
|
+
this.ended = Math.trunc(performance.now());
|
|
89
|
+
this.timedOut = true;
|
|
90
|
+
reject(rejection);
|
|
70
91
|
}
|
|
71
92
|
}
|
|
72
93
|
|
|
@@ -76,20 +97,303 @@ export class Timeout extends Promise<never> {
|
|
|
76
97
|
clear(): void {
|
|
77
98
|
clearTimeout(this.id);
|
|
78
99
|
this.id = undefined;
|
|
100
|
+
this.timedOut = false;
|
|
101
|
+
this.cleared = true;
|
|
79
102
|
}
|
|
80
103
|
|
|
81
|
-
|
|
82
|
-
|
|
104
|
+
throwIfExpired(): void {
|
|
105
|
+
if (this.timedOut) throw new TimeoutError('Timed out', { duration: this.duration });
|
|
83
106
|
}
|
|
84
107
|
|
|
85
|
-
static
|
|
86
|
-
return (
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
108
|
+
public static expires(duration: number, unref?: true): Timeout {
|
|
109
|
+
return new Timeout(undefined, { duration, unref });
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
static override reject(rejection?: Error): Timeout {
|
|
113
|
+
return new Timeout(undefined, { duration: 0, unref: true, rejection });
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** @internal */
|
|
118
|
+
export type TimeoutContextOptions = (LegacyTimeoutContextOptions | CSOTTimeoutContextOptions) & {
|
|
119
|
+
session?: ClientSession;
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
/** @internal */
|
|
123
|
+
export type LegacyTimeoutContextOptions = {
|
|
124
|
+
serverSelectionTimeoutMS: number;
|
|
125
|
+
waitQueueTimeoutMS: number;
|
|
126
|
+
socketTimeoutMS?: number;
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
/** @internal */
|
|
130
|
+
export type CSOTTimeoutContextOptions = {
|
|
131
|
+
timeoutMS: number;
|
|
132
|
+
serverSelectionTimeoutMS: number;
|
|
133
|
+
socketTimeoutMS?: number;
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
function isLegacyTimeoutContextOptions(v: unknown): v is LegacyTimeoutContextOptions {
|
|
137
|
+
return (
|
|
138
|
+
v != null &&
|
|
139
|
+
typeof v === 'object' &&
|
|
140
|
+
'serverSelectionTimeoutMS' in v &&
|
|
141
|
+
typeof v.serverSelectionTimeoutMS === 'number' &&
|
|
142
|
+
'waitQueueTimeoutMS' in v &&
|
|
143
|
+
typeof v.waitQueueTimeoutMS === 'number'
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function isCSOTTimeoutContextOptions(v: unknown): v is CSOTTimeoutContextOptions {
|
|
148
|
+
return (
|
|
149
|
+
v != null &&
|
|
150
|
+
typeof v === 'object' &&
|
|
151
|
+
'serverSelectionTimeoutMS' in v &&
|
|
152
|
+
typeof v.serverSelectionTimeoutMS === 'number' &&
|
|
153
|
+
'timeoutMS' in v &&
|
|
154
|
+
typeof v.timeoutMS === 'number'
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/** @internal */
|
|
159
|
+
export abstract class TimeoutContext {
|
|
160
|
+
static create(options: TimeoutContextOptions): TimeoutContext {
|
|
161
|
+
if (options.session?.timeoutContext != null) return options.session?.timeoutContext;
|
|
162
|
+
if (isCSOTTimeoutContextOptions(options)) return new CSOTTimeoutContext(options);
|
|
163
|
+
else if (isLegacyTimeoutContextOptions(options)) return new LegacyTimeoutContext(options);
|
|
164
|
+
else throw new MongoRuntimeError('Unrecognized options');
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
abstract get maxTimeMS(): number | null;
|
|
168
|
+
|
|
169
|
+
abstract get serverSelectionTimeout(): Timeout | null;
|
|
170
|
+
|
|
171
|
+
abstract get connectionCheckoutTimeout(): Timeout | null;
|
|
172
|
+
|
|
173
|
+
abstract get clearServerSelectionTimeout(): boolean;
|
|
174
|
+
|
|
175
|
+
abstract get timeoutForSocketWrite(): Timeout | null;
|
|
176
|
+
|
|
177
|
+
abstract get timeoutForSocketRead(): Timeout | null;
|
|
178
|
+
|
|
179
|
+
abstract csotEnabled(): this is CSOTTimeoutContext;
|
|
180
|
+
|
|
181
|
+
abstract refresh(): void;
|
|
182
|
+
|
|
183
|
+
abstract clear(): void;
|
|
184
|
+
|
|
185
|
+
/** Returns a new instance of the TimeoutContext, with all timeouts refreshed and restarted. */
|
|
186
|
+
abstract refreshed(): TimeoutContext;
|
|
187
|
+
|
|
188
|
+
abstract addMaxTimeMSToCommand(command: Document, options: { omitMaxTimeMS?: boolean }): void;
|
|
189
|
+
|
|
190
|
+
abstract getSocketTimeoutMS(): number | undefined;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/** @internal */
|
|
194
|
+
export class CSOTTimeoutContext extends TimeoutContext {
|
|
195
|
+
timeoutMS: number;
|
|
196
|
+
serverSelectionTimeoutMS: number;
|
|
197
|
+
socketTimeoutMS?: number;
|
|
198
|
+
|
|
199
|
+
clearServerSelectionTimeout: boolean;
|
|
200
|
+
|
|
201
|
+
private _serverSelectionTimeout?: Timeout | null;
|
|
202
|
+
private _connectionCheckoutTimeout?: Timeout | null;
|
|
203
|
+
public minRoundTripTime = 0;
|
|
204
|
+
public start: number;
|
|
205
|
+
|
|
206
|
+
constructor(options: CSOTTimeoutContextOptions) {
|
|
207
|
+
super();
|
|
208
|
+
this.start = Math.trunc(performance.now());
|
|
209
|
+
|
|
210
|
+
this.timeoutMS = options.timeoutMS;
|
|
211
|
+
|
|
212
|
+
this.serverSelectionTimeoutMS = options.serverSelectionTimeoutMS;
|
|
213
|
+
|
|
214
|
+
this.socketTimeoutMS = options.socketTimeoutMS;
|
|
215
|
+
|
|
216
|
+
this.clearServerSelectionTimeout = false;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
get maxTimeMS(): number {
|
|
220
|
+
return this.remainingTimeMS - this.minRoundTripTime;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
get remainingTimeMS() {
|
|
224
|
+
const timePassed = Math.trunc(performance.now()) - this.start;
|
|
225
|
+
return this.timeoutMS <= 0 ? Infinity : this.timeoutMS - timePassed;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
csotEnabled(): this is CSOTTimeoutContext {
|
|
229
|
+
return true;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
get serverSelectionTimeout(): Timeout | null {
|
|
233
|
+
// check for undefined
|
|
234
|
+
if (typeof this._serverSelectionTimeout !== 'object' || this._serverSelectionTimeout?.cleared) {
|
|
235
|
+
const { remainingTimeMS, serverSelectionTimeoutMS } = this;
|
|
236
|
+
if (remainingTimeMS <= 0)
|
|
237
|
+
return Timeout.reject(
|
|
238
|
+
new MongoOperationTimeoutError(`Timed out in server selection after ${this.timeoutMS}ms`)
|
|
239
|
+
);
|
|
240
|
+
const usingServerSelectionTimeoutMS =
|
|
241
|
+
serverSelectionTimeoutMS !== 0 &&
|
|
242
|
+
csotMin(remainingTimeMS, serverSelectionTimeoutMS) === serverSelectionTimeoutMS;
|
|
243
|
+
if (usingServerSelectionTimeoutMS) {
|
|
244
|
+
this._serverSelectionTimeout = Timeout.expires(serverSelectionTimeoutMS);
|
|
245
|
+
} else {
|
|
246
|
+
if (remainingTimeMS > 0 && Number.isFinite(remainingTimeMS)) {
|
|
247
|
+
this._serverSelectionTimeout = Timeout.expires(remainingTimeMS);
|
|
248
|
+
} else {
|
|
249
|
+
this._serverSelectionTimeout = null;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
return this._serverSelectionTimeout;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
get connectionCheckoutTimeout(): Timeout | null {
|
|
258
|
+
if (
|
|
259
|
+
typeof this._connectionCheckoutTimeout !== 'object' ||
|
|
260
|
+
this._connectionCheckoutTimeout?.cleared
|
|
261
|
+
) {
|
|
262
|
+
if (typeof this._serverSelectionTimeout === 'object') {
|
|
263
|
+
// null or Timeout
|
|
264
|
+
this._connectionCheckoutTimeout = this._serverSelectionTimeout;
|
|
265
|
+
} else {
|
|
266
|
+
throw new MongoRuntimeError(
|
|
267
|
+
'Unreachable. If you are seeing this error, please file a ticket on the NODE driver project on Jira'
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
return this._connectionCheckoutTimeout;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
get timeoutForSocketWrite(): Timeout | null {
|
|
275
|
+
const { remainingTimeMS } = this;
|
|
276
|
+
if (!Number.isFinite(remainingTimeMS)) return null;
|
|
277
|
+
if (remainingTimeMS > 0) return Timeout.expires(remainingTimeMS);
|
|
278
|
+
return Timeout.reject(new MongoOperationTimeoutError('Timed out before socket write'));
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
get timeoutForSocketRead(): Timeout | null {
|
|
282
|
+
const { remainingTimeMS } = this;
|
|
283
|
+
if (!Number.isFinite(remainingTimeMS)) return null;
|
|
284
|
+
if (remainingTimeMS > 0) return Timeout.expires(remainingTimeMS);
|
|
285
|
+
return Timeout.reject(new MongoOperationTimeoutError('Timed out before socket read'));
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
refresh(): void {
|
|
289
|
+
this.start = Math.trunc(performance.now());
|
|
290
|
+
this.minRoundTripTime = 0;
|
|
291
|
+
this._serverSelectionTimeout?.clear();
|
|
292
|
+
this._connectionCheckoutTimeout?.clear();
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
clear(): void {
|
|
296
|
+
this._serverSelectionTimeout?.clear();
|
|
297
|
+
this._connectionCheckoutTimeout?.clear();
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* @internal
|
|
302
|
+
* Throws a MongoOperationTimeoutError if the context has expired.
|
|
303
|
+
* If the context has not expired, returns the `remainingTimeMS`
|
|
304
|
+
**/
|
|
305
|
+
getRemainingTimeMSOrThrow(message?: string): number {
|
|
306
|
+
const { remainingTimeMS } = this;
|
|
307
|
+
if (remainingTimeMS <= 0)
|
|
308
|
+
throw new MongoOperationTimeoutError(message ?? `Expired after ${this.timeoutMS}ms`);
|
|
309
|
+
return remainingTimeMS;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* @internal
|
|
314
|
+
* This method is intended to be used in situations where concurrent operation are on the same deadline, but cannot share a single `TimeoutContext` instance.
|
|
315
|
+
* Returns a new instance of `CSOTTimeoutContext` constructed with identical options, but setting the `start` property to `this.start`.
|
|
316
|
+
*/
|
|
317
|
+
clone(): CSOTTimeoutContext {
|
|
318
|
+
const timeoutContext = new CSOTTimeoutContext({
|
|
319
|
+
timeoutMS: this.timeoutMS,
|
|
320
|
+
serverSelectionTimeoutMS: this.serverSelectionTimeoutMS
|
|
321
|
+
});
|
|
322
|
+
timeoutContext.start = this.start;
|
|
323
|
+
return timeoutContext;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
override refreshed(): CSOTTimeoutContext {
|
|
327
|
+
return new CSOTTimeoutContext(this);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
override addMaxTimeMSToCommand(command: Document, options: { omitMaxTimeMS?: boolean }): void {
|
|
331
|
+
if (options.omitMaxTimeMS) return;
|
|
332
|
+
const maxTimeMS = this.remainingTimeMS - this.minRoundTripTime;
|
|
333
|
+
if (maxTimeMS > 0 && Number.isFinite(maxTimeMS)) command.maxTimeMS = maxTimeMS;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
override getSocketTimeoutMS(): number | undefined {
|
|
337
|
+
return 0;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/** @internal */
|
|
342
|
+
export class LegacyTimeoutContext extends TimeoutContext {
|
|
343
|
+
options: LegacyTimeoutContextOptions;
|
|
344
|
+
clearServerSelectionTimeout: boolean;
|
|
345
|
+
|
|
346
|
+
constructor(options: LegacyTimeoutContextOptions) {
|
|
347
|
+
super();
|
|
348
|
+
this.options = options;
|
|
349
|
+
this.clearServerSelectionTimeout = true;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
csotEnabled(): this is CSOTTimeoutContext {
|
|
353
|
+
return false;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
get serverSelectionTimeout(): Timeout | null {
|
|
357
|
+
if (this.options.serverSelectionTimeoutMS != null && this.options.serverSelectionTimeoutMS > 0)
|
|
358
|
+
return Timeout.expires(this.options.serverSelectionTimeoutMS);
|
|
359
|
+
return null;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
get connectionCheckoutTimeout(): Timeout | null {
|
|
363
|
+
if (this.options.waitQueueTimeoutMS != null && this.options.waitQueueTimeoutMS > 0)
|
|
364
|
+
return Timeout.expires(this.options.waitQueueTimeoutMS);
|
|
365
|
+
return null;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
get timeoutForSocketWrite(): Timeout | null {
|
|
369
|
+
return null;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
get timeoutForSocketRead(): Timeout | null {
|
|
373
|
+
return null;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
refresh(): void {
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
clear(): void {
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
get maxTimeMS() {
|
|
385
|
+
return null;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
override refreshed(): LegacyTimeoutContext {
|
|
389
|
+
return new LegacyTimeoutContext(this.options);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
override addMaxTimeMSToCommand(_command: Document, _options: { omitMaxTimeMS?: boolean }): void {
|
|
393
|
+
// No max timeMS is added to commands in legacy timeout mode.
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
override getSocketTimeoutMS(): number | undefined {
|
|
397
|
+
return this.options.socketTimeoutMS;
|
|
94
398
|
}
|
|
95
399
|
}
|
package/src/transactions.ts
CHANGED
|
@@ -60,7 +60,7 @@ const COMMITTED_STATES: Set<TxnState> = new Set([
|
|
|
60
60
|
* Configuration options for a transaction.
|
|
61
61
|
* @public
|
|
62
62
|
*/
|
|
63
|
-
export interface TransactionOptions extends CommandOperationOptions {
|
|
63
|
+
export interface TransactionOptions extends Omit<CommandOperationOptions, 'timeoutMS'> {
|
|
64
64
|
// TODO(NODE-3344): These options use the proper class forms of these settings, it should accept the basic enum values too
|
|
65
65
|
/** A default read concern for commands in this transaction */
|
|
66
66
|
readConcern?: ReadConcernLike;
|
package/src/utils.ts
CHANGED
|
@@ -26,7 +26,6 @@ import {
|
|
|
26
26
|
MongoParseError,
|
|
27
27
|
MongoRuntimeError
|
|
28
28
|
} from './error';
|
|
29
|
-
import type { Explain, ExplainVerbosity } from './explain';
|
|
30
29
|
import type { MongoClient } from './mongo_client';
|
|
31
30
|
import type { CommandOperationOptions, OperationParent } from './operations/command';
|
|
32
31
|
import type { Hint, OperationOptions } from './operations/operation';
|
|
@@ -36,6 +35,7 @@ import { ServerType } from './sdam/common';
|
|
|
36
35
|
import type { Server } from './sdam/server';
|
|
37
36
|
import type { Topology } from './sdam/topology';
|
|
38
37
|
import type { ClientSession } from './sessions';
|
|
38
|
+
import { type TimeoutContextOptions } from './timeout';
|
|
39
39
|
import { WriteConcern } from './write_concern';
|
|
40
40
|
|
|
41
41
|
/**
|
|
@@ -245,32 +245,6 @@ export function decorateWithReadConcern(
|
|
|
245
245
|
}
|
|
246
246
|
}
|
|
247
247
|
|
|
248
|
-
/**
|
|
249
|
-
* Applies an explain to a given command.
|
|
250
|
-
* @internal
|
|
251
|
-
*
|
|
252
|
-
* @param command - the command on which to apply the explain
|
|
253
|
-
* @param options - the options containing the explain verbosity
|
|
254
|
-
*/
|
|
255
|
-
export function decorateWithExplain(
|
|
256
|
-
command: Document,
|
|
257
|
-
explain: Explain
|
|
258
|
-
): {
|
|
259
|
-
explain: Document;
|
|
260
|
-
verbosity: ExplainVerbosity;
|
|
261
|
-
maxTimeMS?: number;
|
|
262
|
-
} {
|
|
263
|
-
type ExplainCommand = ReturnType<typeof decorateWithExplain>;
|
|
264
|
-
const { verbosity, maxTimeMS } = explain;
|
|
265
|
-
const baseCommand: ExplainCommand = { explain: command, verbosity };
|
|
266
|
-
|
|
267
|
-
if (typeof maxTimeMS === 'number') {
|
|
268
|
-
baseCommand.maxTimeMS = maxTimeMS;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
return baseCommand;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
248
|
/**
|
|
275
249
|
* @internal
|
|
276
250
|
*/
|
|
@@ -515,9 +489,25 @@ export function hasAtomicOperators(doc: Document | Document[]): boolean {
|
|
|
515
489
|
return keys.length > 0 && keys[0][0] === '$';
|
|
516
490
|
}
|
|
517
491
|
|
|
492
|
+
export function resolveTimeoutOptions<T extends Partial<TimeoutContextOptions>>(
|
|
493
|
+
client: MongoClient,
|
|
494
|
+
options: T
|
|
495
|
+
): T &
|
|
496
|
+
Pick<
|
|
497
|
+
MongoClient['s']['options'],
|
|
498
|
+
'timeoutMS' | 'serverSelectionTimeoutMS' | 'waitQueueTimeoutMS' | 'socketTimeoutMS'
|
|
499
|
+
> {
|
|
500
|
+
const { socketTimeoutMS, serverSelectionTimeoutMS, waitQueueTimeoutMS, timeoutMS } =
|
|
501
|
+
client.s.options;
|
|
502
|
+
return { socketTimeoutMS, serverSelectionTimeoutMS, waitQueueTimeoutMS, timeoutMS, ...options };
|
|
503
|
+
}
|
|
518
504
|
/**
|
|
519
505
|
* Merge inherited properties from parent into options, prioritizing values from options,
|
|
520
506
|
* then values from parent.
|
|
507
|
+
*
|
|
508
|
+
* @param parent - An optional owning class of the operation being run. ex. Db/Collection/MongoClient.
|
|
509
|
+
* @param options - The options passed to the operation method.
|
|
510
|
+
*
|
|
521
511
|
* @internal
|
|
522
512
|
*/
|
|
523
513
|
export function resolveOptions<T extends CommandOperationOptions>(
|
|
@@ -526,25 +516,43 @@ export function resolveOptions<T extends CommandOperationOptions>(
|
|
|
526
516
|
): T {
|
|
527
517
|
const result: T = Object.assign({}, options, resolveBSONOptions(options, parent));
|
|
528
518
|
|
|
519
|
+
const timeoutMS = options?.timeoutMS ?? parent?.timeoutMS;
|
|
529
520
|
// Users cannot pass a readConcern/writeConcern to operations in a transaction
|
|
530
521
|
const session = options?.session;
|
|
522
|
+
|
|
531
523
|
if (!session?.inTransaction()) {
|
|
532
524
|
const readConcern = ReadConcern.fromOptions(options) ?? parent?.readConcern;
|
|
533
525
|
if (readConcern) {
|
|
534
526
|
result.readConcern = readConcern;
|
|
535
527
|
}
|
|
536
528
|
|
|
537
|
-
|
|
529
|
+
let writeConcern = WriteConcern.fromOptions(options) ?? parent?.writeConcern;
|
|
538
530
|
if (writeConcern) {
|
|
531
|
+
if (timeoutMS != null) {
|
|
532
|
+
writeConcern = WriteConcern.fromOptions({
|
|
533
|
+
...writeConcern,
|
|
534
|
+
wtimeout: undefined,
|
|
535
|
+
wtimeoutMS: undefined
|
|
536
|
+
});
|
|
537
|
+
}
|
|
539
538
|
result.writeConcern = writeConcern;
|
|
540
539
|
}
|
|
541
540
|
}
|
|
542
541
|
|
|
542
|
+
result.timeoutMS = timeoutMS;
|
|
543
|
+
|
|
543
544
|
const readPreference = ReadPreference.fromOptions(options) ?? parent?.readPreference;
|
|
544
545
|
if (readPreference) {
|
|
545
546
|
result.readPreference = readPreference;
|
|
546
547
|
}
|
|
547
548
|
|
|
549
|
+
const isConvenientTransaction = session?.explicit && session?.timeoutContext != null;
|
|
550
|
+
if (isConvenientTransaction && options?.timeoutMS != null) {
|
|
551
|
+
throw new MongoInvalidArgumentError(
|
|
552
|
+
'An operation cannot be given a timeoutMS setting when inside a withTransaction call that has a timeoutMS setting'
|
|
553
|
+
);
|
|
554
|
+
}
|
|
555
|
+
|
|
548
556
|
return result;
|
|
549
557
|
}
|
|
550
558
|
|
|
@@ -1097,8 +1105,11 @@ export function shuffle<T>(sequence: Iterable<T>, limit = 0): Array<T> {
|
|
|
1097
1105
|
return limit % items.length === 0 ? items : items.slice(lowerBound);
|
|
1098
1106
|
}
|
|
1099
1107
|
|
|
1100
|
-
|
|
1101
|
-
|
|
1108
|
+
/**
|
|
1109
|
+
* TODO(NODE-4936): read concern eligibility for commands should be codified in command construction
|
|
1110
|
+
* @internal
|
|
1111
|
+
* @see https://github.com/mongodb/specifications/blob/master/source/read-write-concern/read-write-concern.md#read-concern
|
|
1112
|
+
*/
|
|
1102
1113
|
export function commandSupportsReadConcern(command: Document): boolean {
|
|
1103
1114
|
if (command.aggregate || command.count || command.distinct || command.find || command.geoNear) {
|
|
1104
1115
|
return true;
|
|
@@ -1398,6 +1409,12 @@ export async function fileIsAccessible(fileName: string, mode?: number) {
|
|
|
1398
1409
|
}
|
|
1399
1410
|
}
|
|
1400
1411
|
|
|
1412
|
+
export function csotMin(duration1: number, duration2: number): number {
|
|
1413
|
+
if (duration1 === 0) return duration2;
|
|
1414
|
+
if (duration2 === 0) return duration1;
|
|
1415
|
+
return Math.min(duration1, duration2);
|
|
1416
|
+
}
|
|
1417
|
+
|
|
1401
1418
|
export function noop() {
|
|
1402
1419
|
return;
|
|
1403
1420
|
}
|
package/src/write_concern.ts
CHANGED
|
@@ -15,7 +15,9 @@ export interface WriteConcernOptions {
|
|
|
15
15
|
export interface WriteConcernSettings {
|
|
16
16
|
/** The write concern */
|
|
17
17
|
w?: W;
|
|
18
|
-
/**
|
|
18
|
+
/**
|
|
19
|
+
* The write concern timeout.
|
|
20
|
+
*/
|
|
19
21
|
wtimeoutMS?: number;
|
|
20
22
|
/** The journal write concern */
|
|
21
23
|
journal?: boolean;
|
|
@@ -28,7 +30,6 @@ export interface WriteConcernSettings {
|
|
|
28
30
|
j?: boolean;
|
|
29
31
|
/**
|
|
30
32
|
* The write concern timeout.
|
|
31
|
-
* @deprecated Will be removed in the next major version. Please use the wtimeoutMS option.
|
|
32
33
|
*/
|
|
33
34
|
wtimeout?: number;
|
|
34
35
|
/**
|
|
@@ -65,7 +66,9 @@ export class WriteConcern {
|
|
|
65
66
|
readonly w?: W;
|
|
66
67
|
/** Request acknowledgment that the write operation has been written to the on-disk journal */
|
|
67
68
|
readonly journal?: boolean;
|
|
68
|
-
/**
|
|
69
|
+
/**
|
|
70
|
+
* Specify a time limit to prevent write operations from blocking indefinitely.
|
|
71
|
+
*/
|
|
69
72
|
readonly wtimeoutMS?: number;
|
|
70
73
|
/**
|
|
71
74
|
* Specify a time limit to prevent write operations from blocking indefinitely.
|