mongodb 6.10.0 → 6.11.0-dev.20241128.sha.4842cd8a

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.
Files changed (228) hide show
  1. package/README.md +2 -0
  2. package/lib/admin.js +3 -2
  3. package/lib/admin.js.map +1 -1
  4. package/lib/beta.d.ts +562 -45
  5. package/lib/bulk/common.js +4 -4
  6. package/lib/bulk/common.js.map +1 -1
  7. package/lib/change_stream.js +111 -51
  8. package/lib/change_stream.js.map +1 -1
  9. package/lib/client-side-encryption/auto_encrypter.js +8 -5
  10. package/lib/client-side-encryption/auto_encrypter.js.map +1 -1
  11. package/lib/client-side-encryption/client_encryption.js +48 -18
  12. package/lib/client-side-encryption/client_encryption.js.map +1 -1
  13. package/lib/client-side-encryption/state_machine.js +43 -29
  14. package/lib/client-side-encryption/state_machine.js.map +1 -1
  15. package/lib/cmap/auth/mongo_credentials.js +5 -2
  16. package/lib/cmap/auth/mongo_credentials.js.map +1 -1
  17. package/lib/cmap/auth/mongodb_aws.js +1 -1
  18. package/lib/cmap/auth/mongodb_aws.js.map +1 -1
  19. package/lib/cmap/auth/mongodb_oidc/k8s_machine_workflow.js +38 -0
  20. package/lib/cmap/auth/mongodb_oidc/k8s_machine_workflow.js.map +1 -0
  21. package/lib/cmap/auth/mongodb_oidc.js +2 -0
  22. package/lib/cmap/auth/mongodb_oidc.js.map +1 -1
  23. package/lib/cmap/connect.js +13 -1
  24. package/lib/cmap/connect.js.map +1 -1
  25. package/lib/cmap/connection.js +75 -17
  26. package/lib/cmap/connection.js.map +1 -1
  27. package/lib/cmap/connection_pool.js +14 -12
  28. package/lib/cmap/connection_pool.js.map +1 -1
  29. package/lib/cmap/wire_protocol/on_data.js +5 -1
  30. package/lib/cmap/wire_protocol/on_data.js.map +1 -1
  31. package/lib/cmap/wire_protocol/responses.js +30 -0
  32. package/lib/cmap/wire_protocol/responses.js.map +1 -1
  33. package/lib/collection.js +62 -3
  34. package/lib/collection.js.map +1 -1
  35. package/lib/connection_string.js +2 -0
  36. package/lib/connection_string.js.map +1 -1
  37. package/lib/cursor/abstract_cursor.js +221 -38
  38. package/lib/cursor/abstract_cursor.js.map +1 -1
  39. package/lib/cursor/aggregation_cursor.js +29 -7
  40. package/lib/cursor/aggregation_cursor.js.map +1 -1
  41. package/lib/cursor/change_stream_cursor.js +2 -2
  42. package/lib/cursor/change_stream_cursor.js.map +1 -1
  43. package/lib/cursor/client_bulk_write_cursor.js +1 -1
  44. package/lib/cursor/client_bulk_write_cursor.js.map +1 -1
  45. package/lib/cursor/find_cursor.js +18 -8
  46. package/lib/cursor/find_cursor.js.map +1 -1
  47. package/lib/cursor/list_collections_cursor.js +1 -1
  48. package/lib/cursor/list_collections_cursor.js.map +1 -1
  49. package/lib/cursor/list_indexes_cursor.js +1 -1
  50. package/lib/cursor/list_indexes_cursor.js.map +1 -1
  51. package/lib/cursor/run_command_cursor.js +6 -4
  52. package/lib/cursor/run_command_cursor.js.map +1 -1
  53. package/lib/db.js +63 -3
  54. package/lib/db.js.map +1 -1
  55. package/lib/error.js +34 -9
  56. package/lib/error.js.map +1 -1
  57. package/lib/explain.js +57 -1
  58. package/lib/explain.js.map +1 -1
  59. package/lib/gridfs/download.js +31 -3
  60. package/lib/gridfs/download.js.map +1 -1
  61. package/lib/gridfs/index.js +49 -14
  62. package/lib/gridfs/index.js.map +1 -1
  63. package/lib/gridfs/upload.js +80 -22
  64. package/lib/gridfs/upload.js.map +1 -1
  65. package/lib/index.js +9 -5
  66. package/lib/index.js.map +1 -1
  67. package/lib/mongo_client.js +70 -1
  68. package/lib/mongo_client.js.map +1 -1
  69. package/lib/operations/aggregate.js +2 -2
  70. package/lib/operations/aggregate.js.map +1 -1
  71. package/lib/operations/bulk_write.js +7 -2
  72. package/lib/operations/bulk_write.js.map +1 -1
  73. package/lib/operations/client_bulk_write/client_bulk_write.js +3 -3
  74. package/lib/operations/client_bulk_write/client_bulk_write.js.map +1 -1
  75. package/lib/operations/client_bulk_write/executor.js +14 -3
  76. package/lib/operations/client_bulk_write/executor.js.map +1 -1
  77. package/lib/operations/command.js +5 -2
  78. package/lib/operations/command.js.map +1 -1
  79. package/lib/operations/count.js +2 -2
  80. package/lib/operations/count.js.map +1 -1
  81. package/lib/operations/create_collection.js +8 -7
  82. package/lib/operations/create_collection.js.map +1 -1
  83. package/lib/operations/delete.js +6 -6
  84. package/lib/operations/delete.js.map +1 -1
  85. package/lib/operations/distinct.js +2 -2
  86. package/lib/operations/distinct.js.map +1 -1
  87. package/lib/operations/drop.js +8 -8
  88. package/lib/operations/drop.js.map +1 -1
  89. package/lib/operations/estimated_document_count.js +2 -2
  90. package/lib/operations/estimated_document_count.js.map +1 -1
  91. package/lib/operations/execute_operation.js +16 -10
  92. package/lib/operations/execute_operation.js.map +1 -1
  93. package/lib/operations/find.js +6 -3
  94. package/lib/operations/find.js.map +1 -1
  95. package/lib/operations/find_and_modify.js +2 -2
  96. package/lib/operations/find_and_modify.js.map +1 -1
  97. package/lib/operations/get_more.js +2 -1
  98. package/lib/operations/get_more.js.map +1 -1
  99. package/lib/operations/indexes.js +6 -6
  100. package/lib/operations/indexes.js.map +1 -1
  101. package/lib/operations/insert.js +6 -6
  102. package/lib/operations/insert.js.map +1 -1
  103. package/lib/operations/kill_cursors.js +5 -2
  104. package/lib/operations/kill_cursors.js.map +1 -1
  105. package/lib/operations/list_collections.js +2 -2
  106. package/lib/operations/list_collections.js.map +1 -1
  107. package/lib/operations/list_databases.js +2 -2
  108. package/lib/operations/list_databases.js.map +1 -1
  109. package/lib/operations/operation.js.map +1 -1
  110. package/lib/operations/profiling_level.js +2 -2
  111. package/lib/operations/profiling_level.js.map +1 -1
  112. package/lib/operations/remove_user.js +2 -2
  113. package/lib/operations/remove_user.js.map +1 -1
  114. package/lib/operations/rename.js +2 -2
  115. package/lib/operations/rename.js.map +1 -1
  116. package/lib/operations/run_command.js +6 -4
  117. package/lib/operations/run_command.js.map +1 -1
  118. package/lib/operations/search_indexes/create.js +5 -2
  119. package/lib/operations/search_indexes/create.js.map +1 -1
  120. package/lib/operations/search_indexes/drop.js +2 -2
  121. package/lib/operations/search_indexes/drop.js.map +1 -1
  122. package/lib/operations/search_indexes/update.js +2 -2
  123. package/lib/operations/search_indexes/update.js.map +1 -1
  124. package/lib/operations/set_profiling_level.js +2 -2
  125. package/lib/operations/set_profiling_level.js.map +1 -1
  126. package/lib/operations/stats.js +2 -2
  127. package/lib/operations/stats.js.map +1 -1
  128. package/lib/operations/update.js +8 -8
  129. package/lib/operations/update.js.map +1 -1
  130. package/lib/operations/validate_collection.js +2 -2
  131. package/lib/operations/validate_collection.js.map +1 -1
  132. package/lib/read_concern.js +1 -1
  133. package/lib/sdam/common.js +0 -7
  134. package/lib/sdam/common.js.map +1 -1
  135. package/lib/sdam/server.js +4 -1
  136. package/lib/sdam/server.js.map +1 -1
  137. package/lib/sdam/server_description.js +4 -2
  138. package/lib/sdam/server_description.js.map +1 -1
  139. package/lib/sdam/server_selection.js +5 -2
  140. package/lib/sdam/server_selection.js.map +1 -1
  141. package/lib/sdam/topology.js +38 -15
  142. package/lib/sdam/topology.js.map +1 -1
  143. package/lib/sessions.js +157 -98
  144. package/lib/sessions.js.map +1 -1
  145. package/lib/timeout.js +231 -16
  146. package/lib/timeout.js.map +1 -1
  147. package/lib/utils.js +36 -19
  148. package/lib/utils.js.map +1 -1
  149. package/lib/write_concern.js.map +1 -1
  150. package/mongodb.d.ts +562 -45
  151. package/package.json +18 -17
  152. package/src/admin.ts +6 -2
  153. package/src/bulk/common.ts +17 -5
  154. package/src/change_stream.ts +127 -52
  155. package/src/client-side-encryption/auto_encrypter.ts +12 -5
  156. package/src/client-side-encryption/client_encryption.ts +103 -20
  157. package/src/client-side-encryption/state_machine.ts +66 -32
  158. package/src/cmap/auth/mongo_credentials.ts +6 -3
  159. package/src/cmap/auth/mongodb_aws.ts +1 -1
  160. package/src/cmap/auth/mongodb_oidc/k8s_machine_workflow.ts +38 -0
  161. package/src/cmap/auth/mongodb_oidc.ts +3 -1
  162. package/src/cmap/connect.ts +18 -1
  163. package/src/cmap/connection.ts +105 -17
  164. package/src/cmap/connection_pool.ts +15 -17
  165. package/src/cmap/handshake/client_metadata.ts +1 -1
  166. package/src/cmap/wire_protocol/on_data.ts +11 -1
  167. package/src/cmap/wire_protocol/responses.ts +35 -1
  168. package/src/collection.ts +81 -9
  169. package/src/connection_string.ts +2 -0
  170. package/src/cursor/abstract_cursor.ts +287 -39
  171. package/src/cursor/aggregation_cursor.ts +54 -8
  172. package/src/cursor/change_stream_cursor.ts +6 -2
  173. package/src/cursor/client_bulk_write_cursor.ts +6 -2
  174. package/src/cursor/find_cursor.ts +40 -9
  175. package/src/cursor/list_collections_cursor.ts +1 -1
  176. package/src/cursor/list_indexes_cursor.ts +1 -1
  177. package/src/cursor/run_command_cursor.ts +50 -5
  178. package/src/db.ts +75 -7
  179. package/src/error.ts +33 -8
  180. package/src/explain.ts +85 -0
  181. package/src/gridfs/download.ts +43 -4
  182. package/src/gridfs/index.ts +64 -16
  183. package/src/gridfs/upload.ts +153 -45
  184. package/src/index.ts +27 -5
  185. package/src/mongo_client.ts +76 -4
  186. package/src/operations/aggregate.ts +10 -2
  187. package/src/operations/bulk_write.ts +9 -2
  188. package/src/operations/client_bulk_write/client_bulk_write.ts +11 -3
  189. package/src/operations/client_bulk_write/executor.ts +15 -3
  190. package/src/operations/command.ts +18 -8
  191. package/src/operations/count.ts +10 -3
  192. package/src/operations/create_collection.ts +14 -7
  193. package/src/operations/delete.ts +15 -6
  194. package/src/operations/distinct.ts +7 -2
  195. package/src/operations/drop.ts +18 -8
  196. package/src/operations/estimated_document_count.ts +7 -2
  197. package/src/operations/execute_operation.ts +22 -13
  198. package/src/operations/find.ts +17 -5
  199. package/src/operations/find_and_modify.ts +7 -2
  200. package/src/operations/get_more.ts +4 -1
  201. package/src/operations/indexes.ts +20 -7
  202. package/src/operations/insert.ts +13 -6
  203. package/src/operations/kill_cursors.ts +10 -2
  204. package/src/operations/list_collections.ts +10 -1
  205. package/src/operations/list_databases.ts +9 -2
  206. package/src/operations/operation.ts +16 -2
  207. package/src/operations/profiling_level.ts +7 -2
  208. package/src/operations/remove_user.ts +7 -2
  209. package/src/operations/rename.ts +7 -2
  210. package/src/operations/run_command.ts +23 -4
  211. package/src/operations/search_indexes/create.ts +10 -2
  212. package/src/operations/search_indexes/drop.ts +7 -2
  213. package/src/operations/search_indexes/update.ts +7 -2
  214. package/src/operations/set_profiling_level.ts +4 -2
  215. package/src/operations/stats.ts +7 -2
  216. package/src/operations/update.ts +16 -8
  217. package/src/operations/validate_collection.ts +7 -2
  218. package/src/read_concern.ts +1 -1
  219. package/src/sdam/common.ts +0 -11
  220. package/src/sdam/server.ts +14 -4
  221. package/src/sdam/server_description.ts +6 -2
  222. package/src/sdam/server_selection.ts +5 -2
  223. package/src/sdam/topology.ts +43 -27
  224. package/src/sessions.ts +206 -120
  225. package/src/timeout.ts +327 -23
  226. package/src/transactions.ts +1 -1
  227. package/src/utils.ts +47 -30
  228. package/src/write_concern.ts +6 -3
@@ -130,7 +130,10 @@ export type SupportedNodeConnectionOptions = SupportedTLSConnectionOptions &
130
130
  export interface MongoClientOptions extends BSONSerializeOptions, SupportedNodeConnectionOptions {
131
131
  /** Specifies the name of the replica set, if the mongod is a member of a replica set. */
132
132
  replicaSet?: string;
133
- /** @internal TODO(NODE-5688): This option is in development and currently has no behaviour. */
133
+ /**
134
+ * @experimental
135
+ * Specifies the time an operation will run until it throws a timeout error
136
+ */
134
137
  timeoutMS?: number;
135
138
  /** Enables or disables TLS/SSL for the connection. */
136
139
  tls?: boolean;
@@ -251,7 +254,7 @@ export interface MongoClientOptions extends BSONSerializeOptions, SupportedNodeC
251
254
  *
252
255
  * @remarks
253
256
  * Automatic encryption is an enterprise only feature that only applies to operations on a collection. Automatic encryption is not supported for operations on a database or view, and operations that are not bypassed will result in error
254
- * (see [libmongocrypt: Auto Encryption Allow-List](https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/client-side-encryption.rst#libmongocrypt-auto-encryption-allow-list)). To bypass automatic encryption for all operations, set bypassAutoEncryption=true in AutoEncryptionOpts.
257
+ * (see [libmongocrypt: Auto Encryption Allow-List](https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/client-side-encryption.md#libmongocrypt-auto-encryption-allow-list)). To bypass automatic encryption for all operations, set bypassAutoEncryption=true in AutoEncryptionOpts.
255
258
  *
256
259
  * Automatic encryption requires the authenticated user to have the [listCollections privilege action](https://www.mongodb.com/docs/manual/reference/command/listCollections/#dbcmd.listCollections).
257
260
  *
@@ -482,6 +485,10 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> implements
482
485
  return this.s.bsonOptions;
483
486
  }
484
487
 
488
+ get timeoutMS(): number | undefined {
489
+ return this.s.options.timeoutMS;
490
+ }
491
+
485
492
  /**
486
493
  * Executes a client bulk write operation, available on server 8.0+.
487
494
  * @param models - The client bulk write models.
@@ -508,6 +515,13 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> implements
508
515
  /**
509
516
  * Connect to MongoDB using a url
510
517
  *
518
+ * @remarks
519
+ * Calling `connect` is optional since the first operation you perform will call `connect` if it's needed.
520
+ * `timeoutMS` will bound the time any operation can take before throwing a timeout error.
521
+ * However, when the operation being run is automatically connecting your `MongoClient` the `timeoutMS` will not apply to the time taken to connect the MongoClient.
522
+ * This means the time to setup the `MongoClient` does not count against `timeoutMS`.
523
+ * If you are using `timeoutMS` we recommend connecting your client explicitly in advance of any operation to avoid this inconsistent execution time.
524
+ *
511
525
  * @see docs.mongodb.org/manual/reference/connection-string/
512
526
  */
513
527
  async connect(): Promise<this> {
@@ -688,7 +702,7 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> implements
688
702
 
689
703
  // Default to db from connection string if not provided
690
704
  if (!dbName) {
691
- dbName = this.options.dbName;
705
+ dbName = this.s.options.dbName;
692
706
  }
693
707
 
694
708
  // Copy the options and add out internal override of the not shared flag
@@ -705,6 +719,13 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> implements
705
719
  * Connect to MongoDB using a url
706
720
  *
707
721
  * @remarks
722
+ * Calling `connect` is optional since the first operation you perform will call `connect` if it's needed.
723
+ * `timeoutMS` will bound the time any operation can take before throwing a timeout error.
724
+ * However, when the operation being run is automatically connecting your `MongoClient` the `timeoutMS` will not apply to the time taken to connect the MongoClient.
725
+ * This means the time to setup the `MongoClient` does not count against `timeoutMS`.
726
+ * If you are using `timeoutMS` we recommend connecting your client explicitly in advance of any operation to avoid this inconsistent execution time.
727
+ *
728
+ * @remarks
708
729
  * The programmatically provided options take precedence over the URI options.
709
730
  *
710
731
  * @see https://www.mongodb.com/docs/manual/reference/connection-string/
@@ -789,6 +810,58 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> implements
789
810
  * - The first is to provide the schema that may be defined for all the data within the current cluster
790
811
  * - 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
791
812
  *
813
+ * @remarks
814
+ * When `timeoutMS` is configured for a change stream, it will have different behaviour depending
815
+ * on whether the change stream is in iterator mode or emitter mode. In both cases, a change
816
+ * stream will time out if it does not receive a change event within `timeoutMS` of the last change
817
+ * event.
818
+ *
819
+ * Note that if a change stream is consistently timing out when watching a collection, database or
820
+ * client that is being changed, then this may be due to the server timing out before it can finish
821
+ * processing the existing oplog. To address this, restart the change stream with a higher
822
+ * `timeoutMS`.
823
+ *
824
+ * If the change stream times out the initial aggregate operation to establish the change stream on
825
+ * the server, then the client will close the change stream. If the getMore calls to the server
826
+ * time out, then the change stream will be left open, but will throw a MongoOperationTimeoutError
827
+ * when in iterator mode and emit an error event that returns a MongoOperationTimeoutError in
828
+ * emitter mode.
829
+ *
830
+ * To determine whether or not the change stream is still open following a timeout, check the
831
+ * {@link ChangeStream.closed} getter.
832
+ *
833
+ * @example
834
+ * In iterator mode, if a next() call throws a timeout error, it will attempt to resume the change stream.
835
+ * The next call can just be retried after this succeeds.
836
+ * ```ts
837
+ * const changeStream = collection.watch([], { timeoutMS: 100 });
838
+ * try {
839
+ * await changeStream.next();
840
+ * } catch (e) {
841
+ * if (e instanceof MongoOperationTimeoutError && !changeStream.closed) {
842
+ * await changeStream.next();
843
+ * }
844
+ * throw e;
845
+ * }
846
+ * ```
847
+ *
848
+ * @example
849
+ * In emitter mode, if the change stream goes `timeoutMS` without emitting a change event, it will
850
+ * emit an error event that returns a MongoOperationTimeoutError, but will not close the change
851
+ * stream unless the resume attempt fails. There is no need to re-establish change listeners as
852
+ * this will automatically continue emitting change events once the resume attempt completes.
853
+ *
854
+ * ```ts
855
+ * const changeStream = collection.watch([], { timeoutMS: 100 });
856
+ * changeStream.on('change', console.log);
857
+ * changeStream.on('error', e => {
858
+ * if (e instanceof MongoOperationTimeoutError && !changeStream.closed) {
859
+ * // do nothing
860
+ * } else {
861
+ * changeStream.close();
862
+ * }
863
+ * });
864
+ * ```
792
865
  * @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.
793
866
  * @param options - Optional settings for the command
794
867
  * @typeParam TSchema - Type of the data being detected by the change stream
@@ -952,6 +1025,5 @@ export interface MongoOptions
952
1025
  * TODO: NODE-5671 - remove internal flag
953
1026
  */
954
1027
  mongodbLogPath?: 'stderr' | 'stdout' | MongoDBLogWritable;
955
- /** @internal TODO(NODE-5688): make this public */
956
1028
  timeoutMS?: number;
957
1029
  }
@@ -1,9 +1,11 @@
1
1
  import type { Document } from '../bson';
2
2
  import { CursorResponse, ExplainedCursorResponse } from '../cmap/wire_protocol/responses';
3
+ import { type CursorTimeoutMode } from '../cursor/abstract_cursor';
3
4
  import { MongoInvalidArgumentError } from '../error';
4
5
  import { type ExplainOptions } from '../explain';
5
6
  import type { Server } from '../sdam/server';
6
7
  import type { ClientSession } from '../sessions';
8
+ import { type TimeoutContext } from '../timeout';
7
9
  import { maxWireVersion, type MongoDBNamespace } from '../utils';
8
10
  import { WriteConcern } from '../write_concern';
9
11
  import { type CollationOptions, CommandOperation, type CommandOperationOptions } from './command';
@@ -24,7 +26,9 @@ export interface AggregateOptions extends Omit<CommandOperationOptions, 'explain
24
26
  bypassDocumentValidation?: boolean;
25
27
  /** Return the query as cursor, on 2.6 \> it returns as a real cursor on pre 2.6 it returns as an emulated cursor. */
26
28
  cursor?: Document;
27
- /** specifies a cumulative time limit in milliseconds for processing operations on the cursor. MongoDB interrupts the operation at the earliest following interrupt point. */
29
+ /**
30
+ * Specifies a cumulative time limit in milliseconds for processing operations on the cursor. MongoDB interrupts the operation at the earliest following interrupt point.
31
+ */
28
32
  maxTimeMS?: number;
29
33
  /** The maximum amount of time for the server to wait on new documents to satisfy a tailable cursor query. */
30
34
  maxAwaitTimeMS?: number;
@@ -43,6 +47,8 @@ export interface AggregateOptions extends Omit<CommandOperationOptions, 'explain
43
47
  * or `db.aggregate().explain()`.
44
48
  */
45
49
  explain?: ExplainOptions['explain'];
50
+ /** @internal */
51
+ timeoutMode?: CursorTimeoutMode;
46
52
  }
47
53
 
48
54
  /** @internal */
@@ -105,7 +111,8 @@ export class AggregateOperation extends CommandOperation<CursorResponse> {
105
111
 
106
112
  override async execute(
107
113
  server: Server,
108
- session: ClientSession | undefined
114
+ session: ClientSession | undefined,
115
+ timeoutContext: TimeoutContext
109
116
  ): Promise<CursorResponse> {
110
117
  const options: AggregateOptions = this.options;
111
118
  const serverWireVersion = maxWireVersion(server);
@@ -150,6 +157,7 @@ export class AggregateOperation extends CommandOperation<CursorResponse> {
150
157
  server,
151
158
  session,
152
159
  command,
160
+ timeoutContext,
153
161
  this.explain ? ExplainedCursorResponse : CursorResponse
154
162
  );
155
163
  }
@@ -7,6 +7,7 @@ import type {
7
7
  import type { Collection } from '../collection';
8
8
  import type { Server } from '../sdam/server';
9
9
  import type { ClientSession } from '../sessions';
10
+ import { type TimeoutContext } from '../timeout';
10
11
  import { AbstractOperation, Aspect, defineAspects } from './operation';
11
12
 
12
13
  /** @internal */
@@ -32,11 +33,17 @@ export class BulkWriteOperation extends AbstractOperation<BulkWriteResult> {
32
33
 
33
34
  override async execute(
34
35
  server: Server,
35
- session: ClientSession | undefined
36
+ session: ClientSession | undefined,
37
+ timeoutContext: TimeoutContext
36
38
  ): Promise<BulkWriteResult> {
37
39
  const coll = this.collection;
38
40
  const operations = this.operations;
39
- const options = { ...this.options, ...this.bsonOptions, readPreference: this.readPreference };
41
+ const options = {
42
+ ...this.options,
43
+ ...this.bsonOptions,
44
+ readPreference: this.readPreference,
45
+ timeoutContext
46
+ };
40
47
 
41
48
  // Create the bulk operation
42
49
  const bulk: BulkOperationBase =
@@ -2,6 +2,7 @@ import { MongoClientBulkWriteExecutionError, ServerType } from '../../beta';
2
2
  import { ClientBulkWriteCursorResponse } from '../../cmap/wire_protocol/responses';
3
3
  import type { Server } from '../../sdam/server';
4
4
  import type { ClientSession } from '../../sessions';
5
+ import { type TimeoutContext } from '../../timeout';
5
6
  import { MongoDBNamespace } from '../../utils';
6
7
  import { CommandOperation } from '../command';
7
8
  import { Aspect, defineAspects } from '../operation';
@@ -43,7 +44,8 @@ export class ClientBulkWriteOperation extends CommandOperation<ClientBulkWriteCu
43
44
  */
44
45
  override async execute(
45
46
  server: Server,
46
- session: ClientSession | undefined
47
+ session: ClientSession | undefined,
48
+ timeoutContext: TimeoutContext
47
49
  ): Promise<ClientBulkWriteCursorResponse> {
48
50
  let command;
49
51
 
@@ -52,7 +54,7 @@ export class ClientBulkWriteOperation extends CommandOperation<ClientBulkWriteCu
52
54
  let connection;
53
55
  if (!session.pinnedConnection) {
54
56
  // Checkout a connection to build the command.
55
- connection = await server.pool.checkOut();
57
+ connection = await server.pool.checkOut({ timeoutContext });
56
58
  // Pin the connection to the session so it get used to execute the command and we do not
57
59
  // perform a double check-in/check-out.
58
60
  session.pin(connection);
@@ -93,7 +95,13 @@ export class ClientBulkWriteOperation extends CommandOperation<ClientBulkWriteCu
93
95
  if (!this.canRetryWrite) {
94
96
  this.options.willRetryWrite = false;
95
97
  }
96
- return await super.executeCommand(server, session, command, ClientBulkWriteCursorResponse);
98
+ return await super.executeCommand(
99
+ server,
100
+ session,
101
+ command,
102
+ timeoutContext,
103
+ ClientBulkWriteCursorResponse
104
+ );
97
105
  }
98
106
  }
99
107
 
@@ -1,4 +1,5 @@
1
1
  import { type Document } from '../../bson';
2
+ import { CursorTimeoutContext, CursorTimeoutMode } from '../../cursor/abstract_cursor';
2
3
  import { ClientBulkWriteCursor } from '../../cursor/client_bulk_write_cursor';
3
4
  import {
4
5
  MongoClientBulkWriteError,
@@ -7,6 +8,8 @@ import {
7
8
  MongoServerError
8
9
  } from '../../error';
9
10
  import { type MongoClient } from '../../mongo_client';
11
+ import { TimeoutContext } from '../../timeout';
12
+ import { resolveTimeoutOptions } from '../../utils';
10
13
  import { WriteConcern } from '../../write_concern';
11
14
  import { executeOperation } from '../execute_operation';
12
15
  import { ClientBulkWriteOperation } from './client_bulk_write';
@@ -53,7 +56,7 @@ export class ClientBulkWriteExecutor {
53
56
 
54
57
  // If no write concern was provided, we inherit one from the client.
55
58
  if (!this.options.writeConcern) {
56
- this.options.writeConcern = WriteConcern.fromOptions(this.client.options);
59
+ this.options.writeConcern = WriteConcern.fromOptions(this.client.s.options);
57
60
  }
58
61
 
59
62
  if (this.options.writeConcern?.w === 0) {
@@ -86,17 +89,26 @@ export class ClientBulkWriteExecutor {
86
89
  pkFactory
87
90
  );
88
91
  // Unacknowledged writes need to execute all batches and return { ok: 1}
92
+ const resolvedOptions = resolveTimeoutOptions(this.client, this.options);
93
+ const context = TimeoutContext.create(resolvedOptions);
94
+
89
95
  if (this.options.writeConcern?.w === 0) {
90
96
  while (commandBuilder.hasNextBatch()) {
91
97
  const operation = new ClientBulkWriteOperation(commandBuilder, this.options);
92
- await executeOperation(this.client, operation);
98
+ await executeOperation(this.client, operation, context);
93
99
  }
94
100
  return ClientBulkWriteResultsMerger.unacknowledged();
95
101
  } else {
96
102
  const resultsMerger = new ClientBulkWriteResultsMerger(this.options);
97
103
  // For each command will will create and exhaust a cursor for the results.
98
104
  while (commandBuilder.hasNextBatch()) {
99
- const cursor = new ClientBulkWriteCursor(this.client, commandBuilder, this.options);
105
+ const cursorContext = new CursorTimeoutContext(context, Symbol());
106
+ const options = {
107
+ ...this.options,
108
+ timeoutContext: cursorContext,
109
+ ...(resolvedOptions.timeoutMS != null && { timeoutMode: CursorTimeoutMode.LIFETIME })
110
+ };
111
+ const cursor = new ClientBulkWriteCursor(this.client, commandBuilder, options);
100
112
  try {
101
113
  await resultsMerger.merge(cursor);
102
114
  } catch (error) {
@@ -1,18 +1,19 @@
1
1
  import type { BSONSerializeOptions, Document } from '../bson';
2
2
  import { type MongoDBResponseConstructor } from '../cmap/wire_protocol/responses';
3
3
  import { MongoInvalidArgumentError } from '../error';
4
- import { Explain, type ExplainOptions } from '../explain';
4
+ import {
5
+ decorateWithExplain,
6
+ Explain,
7
+ type ExplainOptions,
8
+ validateExplainTimeoutOptions
9
+ } from '../explain';
5
10
  import { ReadConcern } from '../read_concern';
6
11
  import type { ReadPreference } from '../read_preference';
7
12
  import type { Server } from '../sdam/server';
8
13
  import { MIN_SECONDARY_WRITE_WIRE_VERSION } from '../sdam/server_selection';
9
14
  import type { ClientSession } from '../sessions';
10
- import {
11
- commandSupportsReadConcern,
12
- decorateWithExplain,
13
- maxWireVersion,
14
- MongoDBNamespace
15
- } from '../utils';
15
+ import { type TimeoutContext } from '../timeout';
16
+ import { commandSupportsReadConcern, maxWireVersion, MongoDBNamespace } from '../utils';
16
17
  import { WriteConcern, type WriteConcernOptions } from '../write_concern';
17
18
  import type { ReadConcernLike } from './../read_concern';
18
19
  import { AbstractOperation, Aspect, type OperationOptions } from './operation';
@@ -39,6 +40,9 @@ export interface CommandOperationOptions
39
40
  readConcern?: ReadConcernLike;
40
41
  /** Collation */
41
42
  collation?: CollationOptions;
43
+ /**
44
+ * maxTimeMS is a server-side time limit in milliseconds for processing an operation.
45
+ */
42
46
  maxTimeMS?: number;
43
47
  /**
44
48
  * Comment to apply to the operation.
@@ -65,6 +69,7 @@ export interface OperationParent {
65
69
  writeConcern?: WriteConcern;
66
70
  readPreference?: ReadPreference;
67
71
  bsonOptions?: BSONSerializeOptions;
72
+ timeoutMS?: number;
68
73
  }
69
74
 
70
75
  /** @internal */
@@ -95,6 +100,7 @@ export abstract class CommandOperation<T> extends AbstractOperation<T> {
95
100
 
96
101
  if (this.hasAspect(Aspect.EXPLAINABLE)) {
97
102
  this.explain = Explain.fromOptions(options);
103
+ if (this.explain) validateExplainTimeoutOptions(this.options, this.explain);
98
104
  } else if (options?.explain != null) {
99
105
  throw new MongoInvalidArgumentError(`Option "explain" is not supported on this command`);
100
106
  }
@@ -111,19 +117,22 @@ export abstract class CommandOperation<T> extends AbstractOperation<T> {
111
117
  server: Server,
112
118
  session: ClientSession | undefined,
113
119
  cmd: Document,
120
+ timeoutContext: TimeoutContext,
114
121
  responseType: T | undefined
115
122
  ): Promise<typeof responseType extends undefined ? Document : InstanceType<T>>;
116
123
 
117
124
  public async executeCommand(
118
125
  server: Server,
119
126
  session: ClientSession | undefined,
120
- cmd: Document
127
+ cmd: Document,
128
+ timeoutContext: TimeoutContext
121
129
  ): Promise<Document>;
122
130
 
123
131
  async executeCommand(
124
132
  server: Server,
125
133
  session: ClientSession | undefined,
126
134
  cmd: Document,
135
+ timeoutContext: TimeoutContext,
127
136
  responseType?: MongoDBResponseConstructor
128
137
  ): Promise<Document> {
129
138
  this.server = server;
@@ -131,6 +140,7 @@ export abstract class CommandOperation<T> extends AbstractOperation<T> {
131
140
  const options = {
132
141
  ...this.options,
133
142
  ...this.bsonOptions,
143
+ timeoutContext,
134
144
  readPreference: this.readPreference,
135
145
  session
136
146
  };
@@ -2,6 +2,7 @@ import type { Document } from '../bson';
2
2
  import type { Collection } from '../collection';
3
3
  import type { Server } from '../sdam/server';
4
4
  import type { ClientSession } from '../sessions';
5
+ import { type TimeoutContext } from '../timeout';
5
6
  import type { MongoDBNamespace } from '../utils';
6
7
  import { CommandOperation, type CommandOperationOptions } from './command';
7
8
  import { Aspect, defineAspects } from './operation';
@@ -12,7 +13,9 @@ export interface CountOptions extends CommandOperationOptions {
12
13
  skip?: number;
13
14
  /** The maximum amounts to count before aborting. */
14
15
  limit?: number;
15
- /** Number of milliseconds to wait before aborting the query. */
16
+ /**
17
+ * Number of milliseconds to wait before aborting the query.
18
+ */
16
19
  maxTimeMS?: number;
17
20
  /** An index name hint for the query. */
18
21
  hint?: string | Document;
@@ -36,7 +39,11 @@ export class CountOperation extends CommandOperation<number> {
36
39
  return 'count' as const;
37
40
  }
38
41
 
39
- override async execute(server: Server, session: ClientSession | undefined): Promise<number> {
42
+ override async execute(
43
+ server: Server,
44
+ session: ClientSession | undefined,
45
+ timeoutContext: TimeoutContext
46
+ ): Promise<number> {
40
47
  const options = this.options;
41
48
  const cmd: Document = {
42
49
  count: this.collectionName,
@@ -59,7 +66,7 @@ export class CountOperation extends CommandOperation<number> {
59
66
  cmd.maxTimeMS = options.maxTimeMS;
60
67
  }
61
68
 
62
- const result = await super.executeCommand(server, session, cmd);
69
+ const result = await super.executeCommand(server, session, cmd, timeoutContext);
63
70
  return result ? result.n : 0;
64
71
  }
65
72
  }
@@ -9,6 +9,7 @@ import { MongoCompatibilityError } from '../error';
9
9
  import type { PkFactory } from '../mongo_client';
10
10
  import type { Server } from '../sdam/server';
11
11
  import type { ClientSession } from '../sessions';
12
+ import { type TimeoutContext } from '../timeout';
12
13
  import { CommandOperation, type CommandOperationOptions } from './command';
13
14
  import { CreateIndexesOperation } from './indexes';
14
15
  import { Aspect, defineAspects } from './operation';
@@ -16,6 +17,7 @@ import { Aspect, defineAspects } from './operation';
16
17
  const ILLEGAL_COMMAND_FIELDS = new Set([
17
18
  'w',
18
19
  'wtimeout',
20
+ 'timeoutMS',
19
21
  'j',
20
22
  'fsync',
21
23
  'autoIndexId',
@@ -124,14 +126,18 @@ export class CreateCollectionOperation extends CommandOperation<Collection> {
124
126
  return 'create' as const;
125
127
  }
126
128
 
127
- override async execute(server: Server, session: ClientSession | undefined): Promise<Collection> {
129
+ override async execute(
130
+ server: Server,
131
+ session: ClientSession | undefined,
132
+ timeoutContext: TimeoutContext
133
+ ): Promise<Collection> {
128
134
  const db = this.db;
129
135
  const name = this.name;
130
136
  const options = this.options;
131
137
 
132
138
  const encryptedFields: Document | undefined =
133
139
  options.encryptedFields ??
134
- db.client.options.autoEncryption?.encryptedFieldsMap?.[`${db.databaseName}.${name}`];
140
+ db.client.s.options.autoEncryption?.encryptedFieldsMap?.[`${db.databaseName}.${name}`];
135
141
 
136
142
  if (encryptedFields) {
137
143
  // Creating a QE collection required min server of 7.0.0
@@ -155,7 +161,7 @@ export class CreateCollectionOperation extends CommandOperation<Collection> {
155
161
  unique: true
156
162
  }
157
163
  });
158
- await createOp.executeWithoutEncryptedFieldsCheck(server, session);
164
+ await createOp.executeWithoutEncryptedFieldsCheck(server, session, timeoutContext);
159
165
  }
160
166
 
161
167
  if (!options.encryptedFields) {
@@ -163,7 +169,7 @@ export class CreateCollectionOperation extends CommandOperation<Collection> {
163
169
  }
164
170
  }
165
171
 
166
- const coll = await this.executeWithoutEncryptedFieldsCheck(server, session);
172
+ const coll = await this.executeWithoutEncryptedFieldsCheck(server, session, timeoutContext);
167
173
 
168
174
  if (encryptedFields) {
169
175
  // Create the required index for queryable encryption support.
@@ -173,7 +179,7 @@ export class CreateCollectionOperation extends CommandOperation<Collection> {
173
179
  { __safeContent__: 1 },
174
180
  {}
175
181
  );
176
- await createIndexOp.execute(server, session);
182
+ await createIndexOp.execute(server, session, timeoutContext);
177
183
  }
178
184
 
179
185
  return coll;
@@ -181,7 +187,8 @@ export class CreateCollectionOperation extends CommandOperation<Collection> {
181
187
 
182
188
  private async executeWithoutEncryptedFieldsCheck(
183
189
  server: Server,
184
- session: ClientSession | undefined
190
+ session: ClientSession | undefined,
191
+ timeoutContext: TimeoutContext
185
192
  ): Promise<Collection> {
186
193
  const db = this.db;
187
194
  const name = this.name;
@@ -198,7 +205,7 @@ export class CreateCollectionOperation extends CommandOperation<Collection> {
198
205
  }
199
206
  }
200
207
  // otherwise just execute the command
201
- await super.executeCommand(server, session, cmd);
208
+ await super.executeCommand(server, session, cmd, timeoutContext);
202
209
  return new Collection(db, name, options);
203
210
  }
204
211
  }
@@ -4,6 +4,7 @@ import { MongoCompatibilityError, MongoServerError } from '../error';
4
4
  import { type TODO_NODE_3286 } from '../mongo_types';
5
5
  import type { Server } from '../sdam/server';
6
6
  import type { ClientSession } from '../sessions';
7
+ import { type TimeoutContext } from '../timeout';
7
8
  import { type MongoDBNamespace } from '../utils';
8
9
  import { type WriteConcernOptions } from '../write_concern';
9
10
  import { type CollationOptions, CommandOperation, type CommandOperationOptions } from './command';
@@ -67,7 +68,8 @@ export class DeleteOperation extends CommandOperation<DeleteResult> {
67
68
 
68
69
  override async execute(
69
70
  server: Server,
70
- session: ClientSession | undefined
71
+ session: ClientSession | undefined,
72
+ timeoutContext: TimeoutContext
71
73
  ): Promise<DeleteResult> {
72
74
  const options = this.options ?? {};
73
75
  const ordered = typeof options.ordered === 'boolean' ? options.ordered : true;
@@ -95,7 +97,12 @@ export class DeleteOperation extends CommandOperation<DeleteResult> {
95
97
  }
96
98
  }
97
99
 
98
- const res: TODO_NODE_3286 = await super.executeCommand(server, session, command);
100
+ const res: TODO_NODE_3286 = await super.executeCommand(
101
+ server,
102
+ session,
103
+ command,
104
+ timeoutContext
105
+ );
99
106
  return res;
100
107
  }
101
108
  }
@@ -107,9 +114,10 @@ export class DeleteOneOperation extends DeleteOperation {
107
114
 
108
115
  override async execute(
109
116
  server: Server,
110
- session: ClientSession | undefined
117
+ session: ClientSession | undefined,
118
+ timeoutContext: TimeoutContext
111
119
  ): Promise<DeleteResult> {
112
- const res: TODO_NODE_3286 = await super.execute(server, session);
120
+ const res: TODO_NODE_3286 = await super.execute(server, session, timeoutContext);
113
121
  if (this.explain) return res;
114
122
  if (res.code) throw new MongoServerError(res);
115
123
  if (res.writeErrors) throw new MongoServerError(res.writeErrors[0]);
@@ -127,9 +135,10 @@ export class DeleteManyOperation extends DeleteOperation {
127
135
 
128
136
  override async execute(
129
137
  server: Server,
130
- session: ClientSession | undefined
138
+ session: ClientSession | undefined,
139
+ timeoutContext: TimeoutContext
131
140
  ): Promise<DeleteResult> {
132
- const res: TODO_NODE_3286 = await super.execute(server, session);
141
+ const res: TODO_NODE_3286 = await super.execute(server, session, timeoutContext);
133
142
  if (this.explain) return res;
134
143
  if (res.code) throw new MongoServerError(res);
135
144
  if (res.writeErrors) throw new MongoServerError(res.writeErrors[0]);
@@ -2,6 +2,7 @@ import type { Document } from '../bson';
2
2
  import type { Collection } from '../collection';
3
3
  import type { Server } from '../sdam/server';
4
4
  import type { ClientSession } from '../sessions';
5
+ import { type TimeoutContext } from '../timeout';
5
6
  import { decorateWithCollation, decorateWithReadConcern } from '../utils';
6
7
  import { CommandOperation, type CommandOperationOptions } from './command';
7
8
  import { Aspect, defineAspects } from './operation';
@@ -42,7 +43,11 @@ export class DistinctOperation extends CommandOperation<any[]> {
42
43
  return 'distinct' as const;
43
44
  }
44
45
 
45
- override async execute(server: Server, session: ClientSession | undefined): Promise<any[]> {
46
+ override async execute(
47
+ server: Server,
48
+ session: ClientSession | undefined,
49
+ timeoutContext: TimeoutContext
50
+ ): Promise<any[]> {
46
51
  const coll = this.collection;
47
52
  const key = this.key;
48
53
  const query = this.query;
@@ -72,7 +77,7 @@ export class DistinctOperation extends CommandOperation<any[]> {
72
77
  // Have we specified collation
73
78
  decorateWithCollation(cmd, coll, options);
74
79
 
75
- const result = await super.executeCommand(server, session, cmd);
80
+ const result = await super.executeCommand(server, session, cmd, timeoutContext);
76
81
 
77
82
  return this.explain ? result : result.values;
78
83
  }
@@ -3,6 +3,7 @@ import type { Db } from '../db';
3
3
  import { MONGODB_ERROR_CODES, MongoServerError } from '../error';
4
4
  import type { Server } from '../sdam/server';
5
5
  import type { ClientSession } from '../sessions';
6
+ import { type TimeoutContext } from '../timeout';
6
7
  import { CommandOperation, type CommandOperationOptions } from './command';
7
8
  import { Aspect, defineAspects } from './operation';
8
9
 
@@ -29,12 +30,16 @@ export class DropCollectionOperation extends CommandOperation<boolean> {
29
30
  return 'drop' as const;
30
31
  }
31
32
 
32
- override async execute(server: Server, session: ClientSession | undefined): Promise<boolean> {
33
+ override async execute(
34
+ server: Server,
35
+ session: ClientSession | undefined,
36
+ timeoutContext: TimeoutContext
37
+ ): Promise<boolean> {
33
38
  const db = this.db;
34
39
  const options = this.options;
35
40
  const name = this.name;
36
41
 
37
- const encryptedFieldsMap = db.client.options.autoEncryption?.encryptedFieldsMap;
42
+ const encryptedFieldsMap = db.client.s.options.autoEncryption?.encryptedFieldsMap;
38
43
  let encryptedFields: Document | undefined =
39
44
  options.encryptedFields ?? encryptedFieldsMap?.[`${db.databaseName}.${name}`];
40
45
 
@@ -57,7 +62,7 @@ export class DropCollectionOperation extends CommandOperation<boolean> {
57
62
  // Drop auxilliary collections, ignoring potential NamespaceNotFound errors.
58
63
  const dropOp = new DropCollectionOperation(db, collectionName);
59
64
  try {
60
- await dropOp.executeWithoutEncryptedFieldsCheck(server, session);
65
+ await dropOp.executeWithoutEncryptedFieldsCheck(server, session, timeoutContext);
61
66
  } catch (err) {
62
67
  if (
63
68
  !(err instanceof MongoServerError) ||
@@ -69,14 +74,15 @@ export class DropCollectionOperation extends CommandOperation<boolean> {
69
74
  }
70
75
  }
71
76
 
72
- return await this.executeWithoutEncryptedFieldsCheck(server, session);
77
+ return await this.executeWithoutEncryptedFieldsCheck(server, session, timeoutContext);
73
78
  }
74
79
 
75
80
  private async executeWithoutEncryptedFieldsCheck(
76
81
  server: Server,
77
- session: ClientSession | undefined
82
+ session: ClientSession | undefined,
83
+ timeoutContext: TimeoutContext
78
84
  ): Promise<boolean> {
79
- await super.executeCommand(server, session, { drop: this.name });
85
+ await super.executeCommand(server, session, { drop: this.name }, timeoutContext);
80
86
  return true;
81
87
  }
82
88
  }
@@ -96,8 +102,12 @@ export class DropDatabaseOperation extends CommandOperation<boolean> {
96
102
  return 'dropDatabase' as const;
97
103
  }
98
104
 
99
- override async execute(server: Server, session: ClientSession | undefined): Promise<boolean> {
100
- await super.executeCommand(server, session, { dropDatabase: 1 });
105
+ override async execute(
106
+ server: Server,
107
+ session: ClientSession | undefined,
108
+ timeoutContext: TimeoutContext
109
+ ): Promise<boolean> {
110
+ await super.executeCommand(server, session, { dropDatabase: 1 }, timeoutContext);
101
111
  return true;
102
112
  }
103
113
  }