mongodb 6.10.0 → 6.11.0

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 +17 -16
  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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mongodb",
3
- "version": "6.10.0",
3
+ "version": "6.11.0",
4
4
  "description": "The official MongoDB driver for Node.js",
5
5
  "main": "lib/index.js",
6
6
  "files": [
@@ -25,8 +25,8 @@
25
25
  "email": "dbx-node@mongodb.com"
26
26
  },
27
27
  "dependencies": {
28
- "@mongodb-js/saslprep": "^1.1.5",
29
- "bson": "^6.7.0",
28
+ "@mongodb-js/saslprep": "^1.1.9",
29
+ "bson": "^6.10.0",
30
30
  "mongodb-connection-string-url": "^3.0.0"
31
31
  },
32
32
  "peerDependencies": {
@@ -62,42 +62,42 @@
62
62
  }
63
63
  },
64
64
  "devDependencies": {
65
- "@aws-sdk/credential-providers": "^3.632.0",
65
+ "@aws-sdk/credential-providers": "^3.686.0",
66
66
  "@iarna/toml": "^2.2.5",
67
67
  "@istanbuljs/nyc-config-typescript": "^1.0.2",
68
- "@microsoft/api-extractor": "^7.47.5",
68
+ "@microsoft/api-extractor": "^7.47.11",
69
69
  "@microsoft/tsdoc-config": "^0.17.0",
70
- "@mongodb-js/zstd": "^1.2.0",
70
+ "@mongodb-js/zstd": "^1.2.2",
71
71
  "@types/chai": "^4.3.17",
72
72
  "@types/chai-subset": "^1.3.5",
73
73
  "@types/express": "^4.17.21",
74
74
  "@types/kerberos": "^1.1.5",
75
- "@types/mocha": "^10.0.7",
76
- "@types/node": "^22.4.1",
75
+ "@types/mocha": "^10.0.9",
76
+ "@types/node": "^22.9.0",
77
77
  "@types/saslprep": "^1.0.3",
78
78
  "@types/semver": "^7.5.8",
79
79
  "@types/sinon": "^17.0.3",
80
80
  "@types/sinon-chai": "^3.2.12",
81
81
  "@types/whatwg-url": "^11.0.5",
82
- "@typescript-eslint/eslint-plugin": "^8.2.0",
83
- "@typescript-eslint/parser": "^8.2.0",
82
+ "@typescript-eslint/eslint-plugin": "8.4.0",
83
+ "@typescript-eslint/parser": "8.4.0",
84
84
  "chai": "^4.4.1",
85
85
  "chai-subset": "^1.6.0",
86
86
  "chalk": "^4.1.2",
87
- "eslint": "^9.0.0",
87
+ "eslint": "9.9.0",
88
88
  "eslint-config-prettier": "^9.1.0",
89
89
  "eslint-plugin-mocha": "^10.4.1",
90
90
  "eslint-plugin-prettier": "^5.2.1",
91
91
  "eslint-plugin-simple-import-sort": "^12.1.1",
92
92
  "eslint-plugin-tsdoc": "^0.3.0",
93
- "eslint-plugin-unused-imports": "^4.0.0",
94
- "express": "^4.19.2",
93
+ "eslint-plugin-unused-imports": "^4.1.4",
94
+ "express": "^4.21.1",
95
95
  "gcp-metadata": "^5.3.0",
96
96
  "js-yaml": "^4.1.0",
97
- "mocha": "^10.4.0",
97
+ "mocha": "^10.8.2",
98
98
  "mocha-sinon": "^2.1.2",
99
99
  "mongodb-client-encryption": "^6.1.0",
100
- "mongodb-legacy": "^6.1.0",
100
+ "mongodb-legacy": "^6.1.3",
101
101
  "nyc": "^15.1.0",
102
102
  "prettier": "^3.3.3",
103
103
  "semver": "^7.6.3",
@@ -107,7 +107,7 @@
107
107
  "socks": "^2.8.1",
108
108
  "source-map-support": "^0.5.21",
109
109
  "ts-node": "^10.9.2",
110
- "tsd": "^0.31.1",
110
+ "tsd": "^0.31.2",
111
111
  "typescript": "5.5",
112
112
  "typescript-cached-transpile": "^0.0.6",
113
113
  "v8-heapsnapshot": "^1.3.1",
@@ -151,6 +151,7 @@
151
151
  "check:oidc-test": "mocha --config test/mocha_mongodb.json test/integration/auth/mongodb_oidc.prose.test.ts",
152
152
  "check:oidc-azure": "mocha --config test/mocha_mongodb.json test/integration/auth/mongodb_oidc_azure.prose.05.test.ts",
153
153
  "check:oidc-gcp": "mocha --config test/mocha_mongodb.json test/integration/auth/mongodb_oidc_gcp.prose.06.test.ts",
154
+ "check:oidc-k8s": "mocha --config test/mocha_mongodb.json test/integration/auth/mongodb_oidc_k8s.prose.07.test.ts",
154
155
  "check:ocsp": "mocha --config test/manual/mocharc.json test/manual/ocsp_support.test.js",
155
156
  "check:kerberos": "nyc mocha --config test/manual/mocharc.json test/manual/kerberos.test.ts",
156
157
  "check:tls": "mocha --config test/manual/mocharc.json test/manual/tls_support.test.ts",
package/src/admin.ts CHANGED
@@ -78,7 +78,8 @@ export class Admin {
78
78
  new RunAdminCommandOperation(command, {
79
79
  ...resolveBSONOptions(options),
80
80
  session: options?.session,
81
- readPreference: options?.readPreference
81
+ readPreference: options?.readPreference,
82
+ timeoutMS: options?.timeoutMS ?? this.s.db.timeoutMS
82
83
  })
83
84
  );
84
85
  }
@@ -154,7 +155,10 @@ export class Admin {
154
155
  * @param options - Optional settings for the command
155
156
  */
156
157
  async listDatabases(options?: ListDatabasesOptions): Promise<ListDatabasesResult> {
157
- return await executeOperation(this.s.db.client, new ListDatabasesOperation(this.s.db, options));
158
+ return await executeOperation(
159
+ this.s.db.client,
160
+ new ListDatabasesOperation(this.s.db, { timeoutMS: this.s.db.timeoutMS, ...options })
161
+ );
158
162
  }
159
163
 
160
164
  /**
@@ -19,6 +19,7 @@ import { makeUpdateStatement, UpdateOperation, type UpdateStatement } from '../o
19
19
  import type { Server } from '../sdam/server';
20
20
  import type { Topology } from '../sdam/topology';
21
21
  import type { ClientSession } from '../sessions';
22
+ import { type TimeoutContext } from '../timeout';
22
23
  import {
23
24
  applyRetryableWrites,
24
25
  getTopology,
@@ -500,7 +501,7 @@ export function mergeBatchResults(
500
501
 
501
502
  async function executeCommands(
502
503
  bulkOperation: BulkOperationBase,
503
- options: BulkWriteOptions
504
+ options: BulkWriteOptions & { timeoutContext?: TimeoutContext | null }
504
505
  ): Promise<BulkWriteResult> {
505
506
  if (bulkOperation.s.batches.length === 0) {
506
507
  return new BulkWriteResult(bulkOperation.s.bulkResult, bulkOperation.isOrdered);
@@ -551,7 +552,11 @@ async function executeCommands(
551
552
  let thrownError = null;
552
553
  let result;
553
554
  try {
554
- result = await executeOperation(bulkOperation.s.collection.client, operation);
555
+ result = await executeOperation(
556
+ bulkOperation.s.collection.client,
557
+ operation,
558
+ finalOptions.timeoutContext
559
+ );
555
560
  } catch (error) {
556
561
  thrownError = error;
557
562
  }
@@ -842,6 +847,9 @@ export interface BulkWriteOptions extends CommandOperationOptions {
842
847
  forceServerObjectId?: boolean;
843
848
  /** Map of parameter names and values that can be accessed using $$var (requires MongoDB 5.0). */
844
849
  let?: Document;
850
+
851
+ /** @internal */
852
+ timeoutContext?: TimeoutContext;
845
853
  }
846
854
 
847
855
  /**
@@ -862,7 +870,11 @@ export class BulkWriteShimOperation extends AbstractOperation {
862
870
  return 'bulkWrite' as const;
863
871
  }
864
872
 
865
- async execute(_server: Server, session: ClientSession | undefined): Promise<any> {
873
+ async execute(
874
+ _server: Server,
875
+ session: ClientSession | undefined,
876
+ timeoutContext: TimeoutContext
877
+ ): Promise<any> {
866
878
  if (this.options.session == null) {
867
879
  // An implicit session could have been created by 'executeOperation'
868
880
  // So if we stick it on finalOptions here, each bulk operation
@@ -870,7 +882,7 @@ export class BulkWriteShimOperation extends AbstractOperation {
870
882
  // an explicit session would be
871
883
  this.options.session = session;
872
884
  }
873
- return await executeCommands(this.bulkOperation, this.options);
885
+ return await executeCommands(this.bulkOperation, { ...this.options, timeoutContext });
874
886
  }
875
887
  }
876
888
 
@@ -1199,7 +1211,7 @@ export abstract class BulkOperationBase {
1199
1211
  const finalOptions = { ...this.s.options, ...options };
1200
1212
  const operation = new BulkWriteShimOperation(this, finalOptions);
1201
1213
 
1202
- return await executeOperation(this.s.collection.client, operation);
1214
+ return await executeOperation(this.s.collection.client, operation, finalOptions.timeoutContext);
1203
1215
  }
1204
1216
 
1205
1217
  /**
@@ -3,7 +3,7 @@ import type { Readable } from 'stream';
3
3
  import type { Binary, Document, Timestamp } from './bson';
4
4
  import { Collection } from './collection';
5
5
  import { CHANGE, CLOSE, END, ERROR, INIT, MORE, RESPONSE, RESUME_TOKEN_CHANGED } from './constants';
6
- import type { AbstractCursorEvents, CursorStreamOptions } from './cursor/abstract_cursor';
6
+ import { type CursorStreamOptions, CursorTimeoutContext } from './cursor/abstract_cursor';
7
7
  import { ChangeStreamCursor, type ChangeStreamCursorOptions } from './cursor/change_stream_cursor';
8
8
  import { Db } from './db';
9
9
  import {
@@ -11,6 +11,7 @@ import {
11
11
  isResumableError,
12
12
  MongoAPIError,
13
13
  MongoChangeStreamError,
14
+ MongoOperationTimeoutError,
14
15
  MongoRuntimeError
15
16
  } from './error';
16
17
  import { MongoClient } from './mongo_client';
@@ -20,6 +21,7 @@ import type { CollationOptions, OperationParent } from './operations/command';
20
21
  import type { ReadPreference } from './read_preference';
21
22
  import { type AsyncDisposable, configureResourceManagement } from './resource_management';
22
23
  import type { ServerSessionId } from './sessions';
24
+ import { CSOTTimeoutContext, type TimeoutContext } from './timeout';
23
25
  import { filterOptions, getTopology, type MongoDBNamespace, squashError } from './utils';
24
26
 
25
27
  /** @internal */
@@ -538,7 +540,14 @@ export type ChangeStreamEvents<
538
540
  end(): void;
539
541
  error(error: Error): void;
540
542
  change(change: TChange): void;
541
- } & AbstractCursorEvents;
543
+ /**
544
+ * @remarks Note that the `close` event is currently emitted whenever the internal `ChangeStreamCursor`
545
+ * instance is closed, which can occur multiple times for a given `ChangeStream` instance.
546
+ *
547
+ * TODO(NODE-6434): address this issue in NODE-6434
548
+ */
549
+ close(): void;
550
+ };
542
551
 
543
552
  /**
544
553
  * Creates a new Change Stream instance. Normally created using {@link Collection#watch|Collection.watch()}.
@@ -609,6 +618,13 @@ export class ChangeStream<
609
618
  */
610
619
  static readonly RESUME_TOKEN_CHANGED = RESUME_TOKEN_CHANGED;
611
620
 
621
+ private timeoutContext?: TimeoutContext;
622
+ /**
623
+ * Note that this property is here to uniquely identify a ChangeStream instance as the owner of
624
+ * the {@link CursorTimeoutContext} instance (see {@link ChangeStream._createChangeStreamCursor}) to ensure
625
+ * that {@link AbstractCursor.close} does not mutate the timeoutContext.
626
+ */
627
+ private contextOwner: symbol;
612
628
  /**
613
629
  * @internal
614
630
  *
@@ -624,20 +640,25 @@ export class ChangeStream<
624
640
 
625
641
  this.pipeline = pipeline;
626
642
  this.options = { ...options };
643
+ let serverSelectionTimeoutMS: number;
627
644
  delete this.options.writeConcern;
628
645
 
629
646
  if (parent instanceof Collection) {
630
647
  this.type = CHANGE_DOMAIN_TYPES.COLLECTION;
648
+ serverSelectionTimeoutMS = parent.s.db.client.options.serverSelectionTimeoutMS;
631
649
  } else if (parent instanceof Db) {
632
650
  this.type = CHANGE_DOMAIN_TYPES.DATABASE;
651
+ serverSelectionTimeoutMS = parent.client.options.serverSelectionTimeoutMS;
633
652
  } else if (parent instanceof MongoClient) {
634
653
  this.type = CHANGE_DOMAIN_TYPES.CLUSTER;
654
+ serverSelectionTimeoutMS = parent.options.serverSelectionTimeoutMS;
635
655
  } else {
636
656
  throw new MongoChangeStreamError(
637
657
  'Parent provided to ChangeStream constructor must be an instance of Collection, Db, or MongoClient'
638
658
  );
639
659
  }
640
660
 
661
+ this.contextOwner = Symbol();
641
662
  this.parent = parent;
642
663
  this.namespace = parent.s.namespace;
643
664
  if (!this.options.readPreference && parent.readPreference) {
@@ -662,6 +683,13 @@ export class ChangeStream<
662
683
  this[kCursorStream]?.removeAllListeners('data');
663
684
  }
664
685
  });
686
+
687
+ if (this.options.timeoutMS != null) {
688
+ this.timeoutContext = new CSOTTimeoutContext({
689
+ timeoutMS: this.options.timeoutMS,
690
+ serverSelectionTimeoutMS
691
+ });
692
+ }
665
693
  }
666
694
 
667
695
  /** @internal */
@@ -681,22 +709,30 @@ export class ChangeStream<
681
709
  // This loop continues until either a change event is received or until a resume attempt
682
710
  // fails.
683
711
 
684
- while (true) {
685
- try {
686
- const hasNext = await this.cursor.hasNext();
687
- return hasNext;
688
- } catch (error) {
712
+ this.timeoutContext?.refresh();
713
+ try {
714
+ while (true) {
689
715
  try {
690
- await this._processErrorIteratorMode(error);
716
+ const hasNext = await this.cursor.hasNext();
717
+ return hasNext;
691
718
  } catch (error) {
692
719
  try {
693
- await this.close();
720
+ await this._processErrorIteratorMode(error, this.cursor.id != null);
694
721
  } catch (error) {
695
- squashError(error);
722
+ if (error instanceof MongoOperationTimeoutError && this.cursor.id == null) {
723
+ throw error;
724
+ }
725
+ try {
726
+ await this.close();
727
+ } catch (error) {
728
+ squashError(error);
729
+ }
730
+ throw error;
696
731
  }
697
- throw error;
698
732
  }
699
733
  }
734
+ } finally {
735
+ this.timeoutContext?.clear();
700
736
  }
701
737
  }
702
738
 
@@ -706,24 +742,32 @@ export class ChangeStream<
706
742
  // Change streams must resume indefinitely while each resume event succeeds.
707
743
  // This loop continues until either a change event is received or until a resume attempt
708
744
  // fails.
745
+ this.timeoutContext?.refresh();
709
746
 
710
- while (true) {
711
- try {
712
- const change = await this.cursor.next();
713
- const processedChange = this._processChange(change ?? null);
714
- return processedChange;
715
- } catch (error) {
747
+ try {
748
+ while (true) {
716
749
  try {
717
- await this._processErrorIteratorMode(error);
750
+ const change = await this.cursor.next();
751
+ const processedChange = this._processChange(change ?? null);
752
+ return processedChange;
718
753
  } catch (error) {
719
754
  try {
720
- await this.close();
755
+ await this._processErrorIteratorMode(error, this.cursor.id != null);
721
756
  } catch (error) {
722
- squashError(error);
757
+ if (error instanceof MongoOperationTimeoutError && this.cursor.id == null) {
758
+ throw error;
759
+ }
760
+ try {
761
+ await this.close();
762
+ } catch (error) {
763
+ squashError(error);
764
+ }
765
+ throw error;
723
766
  }
724
- throw error;
725
767
  }
726
768
  }
769
+ } finally {
770
+ this.timeoutContext?.clear();
727
771
  }
728
772
  }
729
773
 
@@ -735,23 +779,29 @@ export class ChangeStream<
735
779
  // Change streams must resume indefinitely while each resume event succeeds.
736
780
  // This loop continues until either a change event is received or until a resume attempt
737
781
  // fails.
782
+ this.timeoutContext?.refresh();
738
783
 
739
- while (true) {
740
- try {
741
- const change = await this.cursor.tryNext();
742
- return change ?? null;
743
- } catch (error) {
784
+ try {
785
+ while (true) {
744
786
  try {
745
- await this._processErrorIteratorMode(error);
787
+ const change = await this.cursor.tryNext();
788
+ return change ?? null;
746
789
  } catch (error) {
747
790
  try {
748
- await this.close();
791
+ await this._processErrorIteratorMode(error, this.cursor.id != null);
749
792
  } catch (error) {
750
- squashError(error);
793
+ if (error instanceof MongoOperationTimeoutError && this.cursor.id == null) throw error;
794
+ try {
795
+ await this.close();
796
+ } catch (error) {
797
+ squashError(error);
798
+ }
799
+ throw error;
751
800
  }
752
- throw error;
753
801
  }
754
802
  }
803
+ } finally {
804
+ this.timeoutContext?.clear();
755
805
  }
756
806
  }
757
807
 
@@ -784,6 +834,8 @@ export class ChangeStream<
784
834
  * Frees the internal resources used by the change stream.
785
835
  */
786
836
  async close(): Promise<void> {
837
+ this.timeoutContext?.clear();
838
+ this.timeoutContext = undefined;
787
839
  this[kClosed] = true;
788
840
 
789
841
  const cursor = this.cursor;
@@ -866,7 +918,12 @@ export class ChangeStream<
866
918
  client,
867
919
  this.namespace,
868
920
  pipeline,
869
- options
921
+ {
922
+ ...options,
923
+ timeoutContext: this.timeoutContext
924
+ ? new CursorTimeoutContext(this.timeoutContext, this.contextOwner)
925
+ : undefined
926
+ }
870
927
  );
871
928
 
872
929
  for (const event of CHANGE_STREAM_EVENTS) {
@@ -899,8 +956,9 @@ export class ChangeStream<
899
956
  } catch (error) {
900
957
  this.emit(ChangeStream.ERROR, error);
901
958
  }
959
+ this.timeoutContext?.refresh();
902
960
  });
903
- stream.on('error', error => this._processErrorStreamMode(error));
961
+ stream.on('error', error => this._processErrorStreamMode(error, this.cursor.id != null));
904
962
  }
905
963
 
906
964
  /** @internal */
@@ -942,24 +1000,30 @@ export class ChangeStream<
942
1000
  }
943
1001
 
944
1002
  /** @internal */
945
- private _processErrorStreamMode(changeStreamError: AnyError) {
1003
+ private _processErrorStreamMode(changeStreamError: AnyError, cursorInitialized: boolean) {
946
1004
  // If the change stream has been closed explicitly, do not process error.
947
1005
  if (this[kClosed]) return;
948
1006
 
949
- if (this.cursor.id != null && isResumableError(changeStreamError, this.cursor.maxWireVersion)) {
1007
+ if (
1008
+ cursorInitialized &&
1009
+ (isResumableError(changeStreamError, this.cursor.maxWireVersion) ||
1010
+ changeStreamError instanceof MongoOperationTimeoutError)
1011
+ ) {
950
1012
  this._endStream();
951
1013
 
952
- this.cursor.close().then(undefined, squashError);
953
-
954
- const topology = getTopology(this.parent);
955
- topology
956
- .selectServer(this.cursor.readPreference, {
957
- operationName: 'reconnect topology in change stream'
958
- })
959
-
1014
+ this.cursor
1015
+ .close()
1016
+ .then(
1017
+ () => this._resume(changeStreamError),
1018
+ e => {
1019
+ squashError(e);
1020
+ return this._resume(changeStreamError);
1021
+ }
1022
+ )
960
1023
  .then(
961
1024
  () => {
962
- this.cursor = this._createChangeStreamCursor(this.cursor.resumeOptions);
1025
+ if (changeStreamError instanceof MongoOperationTimeoutError)
1026
+ this.emit(ChangeStream.ERROR, changeStreamError);
963
1027
  },
964
1028
  () => this._closeEmitterModeWithError(changeStreamError)
965
1029
  );
@@ -969,33 +1033,44 @@ export class ChangeStream<
969
1033
  }
970
1034
 
971
1035
  /** @internal */
972
- private async _processErrorIteratorMode(changeStreamError: AnyError) {
1036
+ private async _processErrorIteratorMode(changeStreamError: AnyError, cursorInitialized: boolean) {
973
1037
  if (this[kClosed]) {
974
1038
  // TODO(NODE-3485): Replace with MongoChangeStreamClosedError
975
1039
  throw new MongoAPIError(CHANGESTREAM_CLOSED_ERROR);
976
1040
  }
977
1041
 
978
1042
  if (
979
- this.cursor.id == null ||
980
- !isResumableError(changeStreamError, this.cursor.maxWireVersion)
1043
+ cursorInitialized &&
1044
+ (isResumableError(changeStreamError, this.cursor.maxWireVersion) ||
1045
+ changeStreamError instanceof MongoOperationTimeoutError)
981
1046
  ) {
1047
+ try {
1048
+ await this.cursor.close();
1049
+ } catch (error) {
1050
+ squashError(error);
1051
+ }
1052
+
1053
+ await this._resume(changeStreamError);
1054
+
1055
+ if (changeStreamError instanceof MongoOperationTimeoutError) throw changeStreamError;
1056
+ } else {
982
1057
  try {
983
1058
  await this.close();
984
1059
  } catch (error) {
985
1060
  squashError(error);
986
1061
  }
1062
+
987
1063
  throw changeStreamError;
988
1064
  }
1065
+ }
989
1066
 
990
- try {
991
- await this.cursor.close();
992
- } catch (error) {
993
- squashError(error);
994
- }
1067
+ private async _resume(changeStreamError: AnyError) {
1068
+ this.timeoutContext?.refresh();
995
1069
  const topology = getTopology(this.parent);
996
1070
  try {
997
1071
  await topology.selectServer(this.cursor.readPreference, {
998
- operationName: 'reconnect topology in change stream'
1072
+ operationName: 'reconnect topology in change stream',
1073
+ timeoutContext: this.timeoutContext
999
1074
  });
1000
1075
  this.cursor = this._createChangeStreamCursor(this.cursor.resumeOptions);
1001
1076
  } catch {
@@ -310,7 +310,10 @@ export class AutoEncrypter {
310
310
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
311
311
  // @ts-ignore: TS complains as this always returns true on versions where it is present.
312
312
  if (net.getDefaultAutoSelectFamily) {
313
- Object.assign(clientOptions, autoSelectSocketOptions(this._client.options));
313
+ // AutoEncrypter is made inside of MongoClient constructor while options are being parsed,
314
+ // we do not have access to the options that are in progress.
315
+ // TODO(NODE-6449): AutoEncrypter does not use client options for autoSelectFamily
316
+ Object.assign(clientOptions, autoSelectSocketOptions(this._client.s?.options ?? {}));
314
317
  }
315
318
 
316
319
  this._mongocryptdClient = new MongoClient(this._mongocryptdManager.uri, clientOptions);
@@ -392,10 +395,10 @@ export class AutoEncrypter {
392
395
  promoteLongs: false,
393
396
  proxyOptions: this._proxyOptions,
394
397
  tlsOptions: this._tlsOptions,
395
- socketOptions: autoSelectSocketOptions(this._client.options)
398
+ socketOptions: autoSelectSocketOptions(this._client.s.options)
396
399
  });
397
400
 
398
- return deserialize(await stateMachine.execute(this, context), {
401
+ return deserialize(await stateMachine.execute(this, context, options.timeoutContext), {
399
402
  promoteValues: false,
400
403
  promoteLongs: false
401
404
  });
@@ -413,10 +416,14 @@ export class AutoEncrypter {
413
416
  ...options,
414
417
  proxyOptions: this._proxyOptions,
415
418
  tlsOptions: this._tlsOptions,
416
- socketOptions: autoSelectSocketOptions(this._client.options)
419
+ socketOptions: autoSelectSocketOptions(this._client.s.options)
417
420
  });
418
421
 
419
- return await stateMachine.execute(this, context);
422
+ return await stateMachine.execute(
423
+ this,
424
+ context,
425
+ options.timeoutContext?.csotEnabled() ? options.timeoutContext : undefined
426
+ );
420
427
  }
421
428
 
422
429
  /**