mongodb 6.10.0-dev.20241106.sha.dc3fe957 → 6.10.0-dev.20241108.sha.fd7acde6

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 (215) hide show
  1. package/lib/admin.js +3 -2
  2. package/lib/admin.js.map +1 -1
  3. package/lib/beta.d.ts +558 -40
  4. package/lib/bulk/common.js +4 -4
  5. package/lib/bulk/common.js.map +1 -1
  6. package/lib/change_stream.js +111 -51
  7. package/lib/change_stream.js.map +1 -1
  8. package/lib/client-side-encryption/auto_encrypter.js +8 -5
  9. package/lib/client-side-encryption/auto_encrypter.js.map +1 -1
  10. package/lib/client-side-encryption/client_encryption.js +48 -18
  11. package/lib/client-side-encryption/client_encryption.js.map +1 -1
  12. package/lib/client-side-encryption/state_machine.js +43 -29
  13. package/lib/client-side-encryption/state_machine.js.map +1 -1
  14. package/lib/cmap/auth/mongo_credentials.js +2 -1
  15. package/lib/cmap/auth/mongo_credentials.js.map +1 -1
  16. package/lib/cmap/auth/mongodb_oidc/k8s_machine_workflow.js +38 -0
  17. package/lib/cmap/auth/mongodb_oidc/k8s_machine_workflow.js.map +1 -0
  18. package/lib/cmap/auth/mongodb_oidc.js +2 -0
  19. package/lib/cmap/auth/mongodb_oidc.js.map +1 -1
  20. package/lib/cmap/connection.js +78 -6
  21. package/lib/cmap/connection.js.map +1 -1
  22. package/lib/cmap/connection_pool.js +14 -9
  23. package/lib/cmap/connection_pool.js.map +1 -1
  24. package/lib/cmap/wire_protocol/on_data.js +5 -1
  25. package/lib/cmap/wire_protocol/on_data.js.map +1 -1
  26. package/lib/cmap/wire_protocol/responses.js +30 -0
  27. package/lib/cmap/wire_protocol/responses.js.map +1 -1
  28. package/lib/collection.js +62 -3
  29. package/lib/collection.js.map +1 -1
  30. package/lib/connection_string.js +2 -0
  31. package/lib/connection_string.js.map +1 -1
  32. package/lib/cursor/abstract_cursor.js +218 -38
  33. package/lib/cursor/abstract_cursor.js.map +1 -1
  34. package/lib/cursor/aggregation_cursor.js +29 -7
  35. package/lib/cursor/aggregation_cursor.js.map +1 -1
  36. package/lib/cursor/change_stream_cursor.js +2 -2
  37. package/lib/cursor/change_stream_cursor.js.map +1 -1
  38. package/lib/cursor/client_bulk_write_cursor.js +1 -1
  39. package/lib/cursor/client_bulk_write_cursor.js.map +1 -1
  40. package/lib/cursor/find_cursor.js +18 -8
  41. package/lib/cursor/find_cursor.js.map +1 -1
  42. package/lib/cursor/list_collections_cursor.js +1 -1
  43. package/lib/cursor/list_collections_cursor.js.map +1 -1
  44. package/lib/cursor/list_indexes_cursor.js +1 -1
  45. package/lib/cursor/list_indexes_cursor.js.map +1 -1
  46. package/lib/cursor/run_command_cursor.js +6 -4
  47. package/lib/cursor/run_command_cursor.js.map +1 -1
  48. package/lib/db.js +63 -3
  49. package/lib/db.js.map +1 -1
  50. package/lib/error.js +27 -2
  51. package/lib/error.js.map +1 -1
  52. package/lib/explain.js +57 -1
  53. package/lib/explain.js.map +1 -1
  54. package/lib/gridfs/download.js +31 -3
  55. package/lib/gridfs/download.js.map +1 -1
  56. package/lib/gridfs/index.js +49 -14
  57. package/lib/gridfs/index.js.map +1 -1
  58. package/lib/gridfs/upload.js +80 -22
  59. package/lib/gridfs/upload.js.map +1 -1
  60. package/lib/index.js +9 -5
  61. package/lib/index.js.map +1 -1
  62. package/lib/mongo_client.js +70 -1
  63. package/lib/mongo_client.js.map +1 -1
  64. package/lib/operations/aggregate.js +2 -2
  65. package/lib/operations/aggregate.js.map +1 -1
  66. package/lib/operations/bulk_write.js +7 -2
  67. package/lib/operations/bulk_write.js.map +1 -1
  68. package/lib/operations/client_bulk_write/client_bulk_write.js +3 -3
  69. package/lib/operations/client_bulk_write/client_bulk_write.js.map +1 -1
  70. package/lib/operations/client_bulk_write/executor.js +14 -3
  71. package/lib/operations/client_bulk_write/executor.js.map +1 -1
  72. package/lib/operations/command.js +5 -2
  73. package/lib/operations/command.js.map +1 -1
  74. package/lib/operations/count.js +2 -2
  75. package/lib/operations/count.js.map +1 -1
  76. package/lib/operations/create_collection.js +8 -7
  77. package/lib/operations/create_collection.js.map +1 -1
  78. package/lib/operations/delete.js +6 -6
  79. package/lib/operations/delete.js.map +1 -1
  80. package/lib/operations/distinct.js +2 -2
  81. package/lib/operations/distinct.js.map +1 -1
  82. package/lib/operations/drop.js +8 -8
  83. package/lib/operations/drop.js.map +1 -1
  84. package/lib/operations/estimated_document_count.js +2 -2
  85. package/lib/operations/estimated_document_count.js.map +1 -1
  86. package/lib/operations/execute_operation.js +16 -10
  87. package/lib/operations/execute_operation.js.map +1 -1
  88. package/lib/operations/find.js +6 -3
  89. package/lib/operations/find.js.map +1 -1
  90. package/lib/operations/find_and_modify.js +2 -2
  91. package/lib/operations/find_and_modify.js.map +1 -1
  92. package/lib/operations/get_more.js +2 -1
  93. package/lib/operations/get_more.js.map +1 -1
  94. package/lib/operations/indexes.js +6 -6
  95. package/lib/operations/indexes.js.map +1 -1
  96. package/lib/operations/insert.js +6 -6
  97. package/lib/operations/insert.js.map +1 -1
  98. package/lib/operations/kill_cursors.js +5 -2
  99. package/lib/operations/kill_cursors.js.map +1 -1
  100. package/lib/operations/list_collections.js +2 -2
  101. package/lib/operations/list_collections.js.map +1 -1
  102. package/lib/operations/list_databases.js +2 -2
  103. package/lib/operations/list_databases.js.map +1 -1
  104. package/lib/operations/operation.js.map +1 -1
  105. package/lib/operations/profiling_level.js +2 -2
  106. package/lib/operations/profiling_level.js.map +1 -1
  107. package/lib/operations/remove_user.js +2 -2
  108. package/lib/operations/remove_user.js.map +1 -1
  109. package/lib/operations/rename.js +2 -2
  110. package/lib/operations/rename.js.map +1 -1
  111. package/lib/operations/run_command.js +6 -4
  112. package/lib/operations/run_command.js.map +1 -1
  113. package/lib/operations/search_indexes/create.js +5 -2
  114. package/lib/operations/search_indexes/create.js.map +1 -1
  115. package/lib/operations/search_indexes/drop.js +2 -2
  116. package/lib/operations/search_indexes/drop.js.map +1 -1
  117. package/lib/operations/search_indexes/update.js +2 -2
  118. package/lib/operations/search_indexes/update.js.map +1 -1
  119. package/lib/operations/set_profiling_level.js +2 -2
  120. package/lib/operations/set_profiling_level.js.map +1 -1
  121. package/lib/operations/stats.js +2 -2
  122. package/lib/operations/stats.js.map +1 -1
  123. package/lib/operations/update.js +8 -8
  124. package/lib/operations/update.js.map +1 -1
  125. package/lib/operations/validate_collection.js +2 -2
  126. package/lib/operations/validate_collection.js.map +1 -1
  127. package/lib/sdam/common.js +0 -7
  128. package/lib/sdam/common.js.map +1 -1
  129. package/lib/sdam/server.js +4 -1
  130. package/lib/sdam/server.js.map +1 -1
  131. package/lib/sdam/server_description.js +2 -0
  132. package/lib/sdam/server_description.js.map +1 -1
  133. package/lib/sdam/topology.js +38 -15
  134. package/lib/sdam/topology.js.map +1 -1
  135. package/lib/sessions.js +145 -74
  136. package/lib/sessions.js.map +1 -1
  137. package/lib/timeout.js +217 -16
  138. package/lib/timeout.js.map +1 -1
  139. package/lib/utils.js +31 -17
  140. package/lib/utils.js.map +1 -1
  141. package/lib/write_concern.js.map +1 -1
  142. package/mongodb.d.ts +558 -40
  143. package/package.json +3 -2
  144. package/src/admin.ts +6 -2
  145. package/src/bulk/common.ts +17 -5
  146. package/src/change_stream.ts +127 -52
  147. package/src/client-side-encryption/auto_encrypter.ts +12 -5
  148. package/src/client-side-encryption/client_encryption.ts +103 -20
  149. package/src/client-side-encryption/state_machine.ts +66 -32
  150. package/src/cmap/auth/mongo_credentials.ts +3 -2
  151. package/src/cmap/auth/mongodb_oidc/k8s_machine_workflow.ts +38 -0
  152. package/src/cmap/auth/mongodb_oidc.ts +3 -1
  153. package/src/cmap/connection.ts +105 -8
  154. package/src/cmap/connection_pool.ts +14 -14
  155. package/src/cmap/wire_protocol/on_data.ts +11 -1
  156. package/src/cmap/wire_protocol/responses.ts +35 -1
  157. package/src/collection.ts +81 -9
  158. package/src/connection_string.ts +2 -0
  159. package/src/cursor/abstract_cursor.ts +286 -39
  160. package/src/cursor/aggregation_cursor.ts +54 -8
  161. package/src/cursor/change_stream_cursor.ts +6 -2
  162. package/src/cursor/client_bulk_write_cursor.ts +6 -2
  163. package/src/cursor/find_cursor.ts +40 -9
  164. package/src/cursor/list_collections_cursor.ts +1 -1
  165. package/src/cursor/list_indexes_cursor.ts +1 -1
  166. package/src/cursor/run_command_cursor.ts +50 -5
  167. package/src/db.ts +75 -7
  168. package/src/error.ts +26 -1
  169. package/src/explain.ts +85 -0
  170. package/src/gridfs/download.ts +43 -4
  171. package/src/gridfs/index.ts +64 -16
  172. package/src/gridfs/upload.ts +152 -45
  173. package/src/index.ts +27 -5
  174. package/src/mongo_client.ts +75 -3
  175. package/src/operations/aggregate.ts +10 -2
  176. package/src/operations/bulk_write.ts +9 -2
  177. package/src/operations/client_bulk_write/client_bulk_write.ts +11 -3
  178. package/src/operations/client_bulk_write/executor.ts +15 -3
  179. package/src/operations/command.ts +18 -8
  180. package/src/operations/count.ts +10 -3
  181. package/src/operations/create_collection.ts +14 -7
  182. package/src/operations/delete.ts +15 -6
  183. package/src/operations/distinct.ts +7 -2
  184. package/src/operations/drop.ts +18 -8
  185. package/src/operations/estimated_document_count.ts +7 -2
  186. package/src/operations/execute_operation.ts +22 -13
  187. package/src/operations/find.ts +17 -5
  188. package/src/operations/find_and_modify.ts +7 -2
  189. package/src/operations/get_more.ts +4 -1
  190. package/src/operations/indexes.ts +20 -7
  191. package/src/operations/insert.ts +13 -6
  192. package/src/operations/kill_cursors.ts +10 -2
  193. package/src/operations/list_collections.ts +10 -1
  194. package/src/operations/list_databases.ts +9 -2
  195. package/src/operations/operation.ts +16 -2
  196. package/src/operations/profiling_level.ts +7 -2
  197. package/src/operations/remove_user.ts +7 -2
  198. package/src/operations/rename.ts +7 -2
  199. package/src/operations/run_command.ts +23 -4
  200. package/src/operations/search_indexes/create.ts +10 -2
  201. package/src/operations/search_indexes/drop.ts +7 -2
  202. package/src/operations/search_indexes/update.ts +7 -2
  203. package/src/operations/set_profiling_level.ts +4 -2
  204. package/src/operations/stats.ts +7 -2
  205. package/src/operations/update.ts +16 -8
  206. package/src/operations/validate_collection.ts +7 -2
  207. package/src/sdam/common.ts +0 -11
  208. package/src/sdam/server.ts +14 -4
  209. package/src/sdam/server_description.ts +4 -0
  210. package/src/sdam/topology.ts +43 -27
  211. package/src/sessions.ts +193 -89
  212. package/src/timeout.ts +310 -23
  213. package/src/transactions.ts +1 -1
  214. package/src/utils.ts +42 -28
  215. package/src/write_concern.ts +6 -3
@@ -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 { CommandOperation, type CommandOperationOptions } from './command';
6
7
  import { Aspect, defineAspects } from './operation';
7
8
 
@@ -30,7 +31,11 @@ export class EstimatedDocumentCountOperation extends CommandOperation<number> {
30
31
  return 'count' as const;
31
32
  }
32
33
 
33
- override async execute(server: Server, session: ClientSession | undefined): Promise<number> {
34
+ override async execute(
35
+ server: Server,
36
+ session: ClientSession | undefined,
37
+ timeoutContext: TimeoutContext
38
+ ): Promise<number> {
34
39
  const cmd: Document = { count: this.collectionName };
35
40
 
36
41
  if (typeof this.options.maxTimeMS === 'number') {
@@ -43,7 +48,7 @@ export class EstimatedDocumentCountOperation extends CommandOperation<number> {
43
48
  cmd.comment = this.options.comment;
44
49
  }
45
50
 
46
- const response = await super.executeCommand(server, session, cmd);
51
+ const response = await super.executeCommand(server, session, cmd, timeoutContext);
47
52
 
48
53
  return response?.n || 0;
49
54
  }
@@ -24,6 +24,7 @@ import {
24
24
  } from '../sdam/server_selection';
25
25
  import type { Topology } from '../sdam/topology';
26
26
  import type { ClientSession } from '../sessions';
27
+ import { TimeoutContext } from '../timeout';
27
28
  import { supportsRetryableWrites } from '../utils';
28
29
  import { AbstractOperation, Aspect } from './operation';
29
30
 
@@ -57,7 +58,7 @@ type ResultTypeFromOperation<TOperation> =
57
58
  export async function executeOperation<
58
59
  T extends AbstractOperation<TResult>,
59
60
  TResult = ResultTypeFromOperation<T>
60
- >(client: MongoClient, operation: T): Promise<TResult> {
61
+ >(client: MongoClient, operation: T, timeoutContext?: TimeoutContext | null): Promise<TResult> {
61
62
  if (!(operation instanceof AbstractOperation)) {
62
63
  // TODO(NODE-3483): Extend MongoRuntimeError
63
64
  throw new MongoRuntimeError('This method requires a valid operation instance');
@@ -80,11 +81,6 @@ export async function executeOperation<
80
81
  } else if (session.client !== client) {
81
82
  throw new MongoInvalidArgumentError('ClientSession must be from the same MongoClient');
82
83
  }
83
- if (session.explicit && session?.timeoutMS != null && operation.options.timeoutMS != null) {
84
- throw new MongoInvalidArgumentError(
85
- 'Do not specify timeoutMS on operation if already specified on an explicit session'
86
- );
87
- }
88
84
 
89
85
  const readPreference = operation.readPreference ?? ReadPreference.primary;
90
86
  const inTransaction = !!session?.inTransaction();
@@ -105,9 +101,17 @@ export async function executeOperation<
105
101
  session.unpin();
106
102
  }
107
103
 
104
+ timeoutContext ??= TimeoutContext.create({
105
+ session,
106
+ serverSelectionTimeoutMS: client.s.options.serverSelectionTimeoutMS,
107
+ waitQueueTimeoutMS: client.s.options.waitQueueTimeoutMS,
108
+ timeoutMS: operation.options.timeoutMS
109
+ });
110
+
108
111
  try {
109
112
  return await tryOperation(operation, {
110
113
  topology,
114
+ timeoutContext,
111
115
  session,
112
116
  readPreference
113
117
  });
@@ -148,6 +152,7 @@ type RetryOptions = {
148
152
  session: ClientSession | undefined;
149
153
  readPreference: ReadPreference;
150
154
  topology: Topology;
155
+ timeoutContext: TimeoutContext;
151
156
  };
152
157
 
153
158
  /**
@@ -171,7 +176,10 @@ type RetryOptions = {
171
176
  async function tryOperation<
172
177
  T extends AbstractOperation<TResult>,
173
178
  TResult = ResultTypeFromOperation<T>
174
- >(operation: T, { topology, session, readPreference }: RetryOptions): Promise<TResult> {
179
+ >(
180
+ operation: T,
181
+ { topology, timeoutContext, session, readPreference }: RetryOptions
182
+ ): Promise<TResult> {
175
183
  let selector: ReadPreference | ServerSelector;
176
184
 
177
185
  if (operation.hasAspect(Aspect.MUST_SELECT_SAME_SERVER)) {
@@ -189,7 +197,8 @@ async function tryOperation<
189
197
 
190
198
  let server = await topology.selectServer(selector, {
191
199
  session,
192
- operationName: operation.commandName
200
+ operationName: operation.commandName,
201
+ timeoutContext
193
202
  });
194
203
 
195
204
  const hasReadAspect = operation.hasAspect(Aspect.READ_OPERATION);
@@ -214,12 +223,10 @@ async function tryOperation<
214
223
  session.incrementTransactionNumber();
215
224
  }
216
225
 
217
- // TODO(NODE-6231): implement infinite retry within CSOT timeout here
218
- const maxTries = willRetry ? 2 : 1;
226
+ const maxTries = willRetry ? (timeoutContext.csotEnabled() ? Infinity : 2) : 1;
219
227
  let previousOperationError: MongoError | undefined;
220
228
  let previousServer: ServerDescription | undefined;
221
229
 
222
- // TODO(NODE-6231): implement infinite retry within CSOT timeout here
223
230
  for (let tries = 0; tries < maxTries; tries++) {
224
231
  if (previousOperationError) {
225
232
  if (hasWriteAspect && previousOperationError.code === MMAPv1_RETRY_WRITES_ERROR_CODE) {
@@ -268,10 +275,9 @@ async function tryOperation<
268
275
  if (tries > 0 && operation.hasAspect(Aspect.COMMAND_BATCHING)) {
269
276
  operation.resetBatch();
270
277
  }
271
- return await operation.execute(server, session);
278
+ return await operation.execute(server, session, timeoutContext);
272
279
  } catch (operationError) {
273
280
  if (!(operationError instanceof MongoError)) throw operationError;
274
-
275
281
  if (
276
282
  previousOperationError != null &&
277
283
  operationError.hasErrorLabel(MongoErrorLabel.NoWritesPerformed)
@@ -280,6 +286,9 @@ async function tryOperation<
280
286
  }
281
287
  previousServer = server.description;
282
288
  previousOperationError = operationError;
289
+
290
+ // Reset timeouts
291
+ timeoutContext.clear();
283
292
  }
284
293
  }
285
294
 
@@ -1,12 +1,18 @@
1
1
  import type { Document } from '../bson';
2
2
  import { CursorResponse, ExplainedCursorResponse } from '../cmap/wire_protocol/responses';
3
+ import { type AbstractCursorOptions, type CursorTimeoutMode } from '../cursor/abstract_cursor';
3
4
  import { MongoInvalidArgumentError } from '../error';
4
- import { type ExplainOptions } from '../explain';
5
+ import {
6
+ decorateWithExplain,
7
+ type ExplainOptions,
8
+ validateExplainTimeoutOptions
9
+ } from '../explain';
5
10
  import { ReadConcern } from '../read_concern';
6
11
  import type { Server } from '../sdam/server';
7
12
  import type { ClientSession } from '../sessions';
8
13
  import { formatSort, type Sort } from '../sort';
9
- import { decorateWithExplain, type MongoDBNamespace, normalizeHintField } from '../utils';
14
+ import { type TimeoutContext } from '../timeout';
15
+ import { type MongoDBNamespace, normalizeHintField } from '../utils';
10
16
  import { type CollationOptions, CommandOperation, type CommandOperationOptions } from './command';
11
17
  import { Aspect, defineAspects, type Hint } from './operation';
12
18
 
@@ -16,7 +22,8 @@ import { Aspect, defineAspects, type Hint } from './operation';
16
22
  */
17
23
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
18
24
  export interface FindOptions<TSchema extends Document = Document>
19
- extends Omit<CommandOperationOptions, 'writeConcern' | 'explain'> {
25
+ extends Omit<CommandOperationOptions, 'writeConcern' | 'explain'>,
26
+ AbstractCursorOptions {
20
27
  /** Sets the limit of documents returned in the query. */
21
28
  limit?: number;
22
29
  /** Set to sort the documents coming back from the query. Array of indexes, `[['a', 1]]` etc. */
@@ -70,6 +77,8 @@ export interface FindOptions<TSchema extends Document = Document>
70
77
  * @deprecated This API is deprecated in favor of `collection.find().explain()`.
71
78
  */
72
79
  explain?: ExplainOptions['explain'];
80
+ /** @internal*/
81
+ timeoutMode?: CursorTimeoutMode;
73
82
  }
74
83
 
75
84
  /** @internal */
@@ -105,7 +114,8 @@ export class FindOperation extends CommandOperation<CursorResponse> {
105
114
 
106
115
  override async execute(
107
116
  server: Server,
108
- session: ClientSession | undefined
117
+ session: ClientSession | undefined,
118
+ timeoutContext: TimeoutContext
109
119
  ): Promise<CursorResponse> {
110
120
  this.server = server;
111
121
 
@@ -113,6 +123,7 @@ export class FindOperation extends CommandOperation<CursorResponse> {
113
123
 
114
124
  let findCommand = makeFindCommand(this.ns, this.filter, options);
115
125
  if (this.explain) {
126
+ validateExplainTimeoutOptions(this.options, this.explain);
116
127
  findCommand = decorateWithExplain(findCommand, this.explain);
117
128
  }
118
129
 
@@ -123,7 +134,8 @@ export class FindOperation extends CommandOperation<CursorResponse> {
123
134
  ...this.options,
124
135
  ...this.bsonOptions,
125
136
  documentsReturnedIn: 'firstBatch',
126
- session
137
+ session,
138
+ timeoutContext
127
139
  },
128
140
  this.explain ? ExplainedCursorResponse : CursorResponse
129
141
  );
@@ -5,6 +5,7 @@ import { ReadPreference } from '../read_preference';
5
5
  import type { Server } from '../sdam/server';
6
6
  import type { ClientSession } from '../sessions';
7
7
  import { formatSort, type Sort, type SortForCmd } from '../sort';
8
+ import { type TimeoutContext } from '../timeout';
8
9
  import { decorateWithCollation, hasAtomicOperators, maxWireVersion } from '../utils';
9
10
  import { type WriteConcern, type WriteConcernSettings } from '../write_concern';
10
11
  import { CommandOperation, type CommandOperationOptions } from './command';
@@ -180,7 +181,11 @@ export class FindAndModifyOperation extends CommandOperation<Document> {
180
181
  return 'findAndModify' as const;
181
182
  }
182
183
 
183
- override async execute(server: Server, session: ClientSession | undefined): Promise<Document> {
184
+ override async execute(
185
+ server: Server,
186
+ session: ClientSession | undefined,
187
+ timeoutContext: TimeoutContext
188
+ ): Promise<Document> {
184
189
  const coll = this.collection;
185
190
  const query = this.query;
186
191
  const options = { ...this.options, ...this.bsonOptions };
@@ -208,7 +213,7 @@ export class FindAndModifyOperation extends CommandOperation<Document> {
208
213
  }
209
214
 
210
215
  // Execute the command
211
- const result = await super.executeCommand(server, session, cmd);
216
+ const result = await super.executeCommand(server, session, cmd, timeoutContext);
212
217
  return options.includeResultMetadata ? result : (result.value ?? null);
213
218
  }
214
219
  }
@@ -3,6 +3,7 @@ import { CursorResponse } from '../cmap/wire_protocol/responses';
3
3
  import { MongoRuntimeError } 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 { maxWireVersion, type MongoDBNamespace } from '../utils';
7
8
  import { AbstractOperation, Aspect, defineAspects, type OperationOptions } from './operation';
8
9
 
@@ -58,7 +59,8 @@ export class GetMoreOperation extends AbstractOperation {
58
59
  */
59
60
  override async execute(
60
61
  server: Server,
61
- _session: ClientSession | undefined
62
+ _session: ClientSession | undefined,
63
+ timeoutContext: TimeoutContext
62
64
  ): Promise<CursorResponse> {
63
65
  if (server !== this.server) {
64
66
  throw new MongoRuntimeError('Getmore must run on the same server operation began on');
@@ -97,6 +99,7 @@ export class GetMoreOperation extends AbstractOperation {
97
99
  const commandOptions = {
98
100
  returnFieldSelector: null,
99
101
  documentsReturnedIn: 'nextBatch',
102
+ timeoutContext,
100
103
  ...this.options
101
104
  };
102
105
 
@@ -6,6 +6,7 @@ import { MongoCompatibilityError } from '../error';
6
6
  import { type OneOrMore } from '../mongo_types';
7
7
  import type { Server } from '../sdam/server';
8
8
  import type { ClientSession } from '../sessions';
9
+ import { type TimeoutContext } from '../timeout';
9
10
  import { isObject, maxWireVersion, type MongoDBNamespace } from '../utils';
10
11
  import {
11
12
  type CollationOptions,
@@ -296,7 +297,11 @@ export class CreateIndexesOperation extends CommandOperation<string[]> {
296
297
  return 'createIndexes';
297
298
  }
298
299
 
299
- override async execute(server: Server, session: ClientSession | undefined): Promise<string[]> {
300
+ override async execute(
301
+ server: Server,
302
+ session: ClientSession | undefined,
303
+ timeoutContext: TimeoutContext
304
+ ): Promise<string[]> {
300
305
  const options = this.options;
301
306
  const indexes = this.indexes;
302
307
 
@@ -316,7 +321,7 @@ export class CreateIndexesOperation extends CommandOperation<string[]> {
316
321
  // collation is set on each index, it should not be defined at the root
317
322
  this.options.collation = undefined;
318
323
 
319
- await super.executeCommand(server, session, cmd);
324
+ await super.executeCommand(server, session, cmd, timeoutContext);
320
325
 
321
326
  const indexNames = indexes.map(index => index.name || '');
322
327
  return indexNames;
@@ -344,14 +349,21 @@ export class DropIndexOperation extends CommandOperation<Document> {
344
349
  return 'dropIndexes' as const;
345
350
  }
346
351
 
347
- override async execute(server: Server, session: ClientSession | undefined): Promise<Document> {
352
+ override async execute(
353
+ server: Server,
354
+ session: ClientSession | undefined,
355
+ timeoutContext: TimeoutContext
356
+ ): Promise<Document> {
348
357
  const cmd = { dropIndexes: this.collection.collectionName, index: this.indexName };
349
- return await super.executeCommand(server, session, cmd);
358
+ return await super.executeCommand(server, session, cmd, timeoutContext);
350
359
  }
351
360
  }
352
361
 
353
362
  /** @public */
354
- export type ListIndexesOptions = AbstractCursorOptions;
363
+ export type ListIndexesOptions = AbstractCursorOptions & {
364
+ /** @internal */
365
+ omitMaxTimeMS?: boolean;
366
+ };
355
367
 
356
368
  /** @internal */
357
369
  export class ListIndexesOperation extends CommandOperation<CursorResponse> {
@@ -379,7 +391,8 @@ export class ListIndexesOperation extends CommandOperation<CursorResponse> {
379
391
 
380
392
  override async execute(
381
393
  server: Server,
382
- session: ClientSession | undefined
394
+ session: ClientSession | undefined,
395
+ timeoutContext: TimeoutContext
383
396
  ): Promise<CursorResponse> {
384
397
  const serverWireVersion = maxWireVersion(server);
385
398
 
@@ -393,7 +406,7 @@ export class ListIndexesOperation extends CommandOperation<CursorResponse> {
393
406
  command.comment = this.options.comment;
394
407
  }
395
408
 
396
- return await super.executeCommand(server, session, command, CursorResponse);
409
+ return await super.executeCommand(server, session, command, timeoutContext, CursorResponse);
397
410
  }
398
411
  }
399
412
 
@@ -5,6 +5,7 @@ import { MongoInvalidArgumentError, MongoServerError } from '../error';
5
5
  import type { InferIdType } from '../mongo_types';
6
6
  import type { Server } from '../sdam/server';
7
7
  import type { ClientSession } from '../sessions';
8
+ import { type TimeoutContext } from '../timeout';
8
9
  import { maybeAddIdToDocuments, type MongoDBNamespace } from '../utils';
9
10
  import { WriteConcern } from '../write_concern';
10
11
  import { BulkWriteOperation } from './bulk_write';
@@ -27,7 +28,11 @@ export class InsertOperation extends CommandOperation<Document> {
27
28
  return 'insert' as const;
28
29
  }
29
30
 
30
- override async execute(server: Server, session: ClientSession | undefined): Promise<Document> {
31
+ override async execute(
32
+ server: Server,
33
+ session: ClientSession | undefined,
34
+ timeoutContext: TimeoutContext
35
+ ): Promise<Document> {
31
36
  const options = this.options ?? {};
32
37
  const ordered = typeof options.ordered === 'boolean' ? options.ordered : true;
33
38
  const command: Document = {
@@ -46,7 +51,7 @@ export class InsertOperation extends CommandOperation<Document> {
46
51
  command.comment = options.comment;
47
52
  }
48
53
 
49
- return await super.executeCommand(server, session, command);
54
+ return await super.executeCommand(server, session, command, timeoutContext);
50
55
  }
51
56
  }
52
57
 
@@ -73,9 +78,10 @@ export class InsertOneOperation extends InsertOperation {
73
78
 
74
79
  override async execute(
75
80
  server: Server,
76
- session: ClientSession | undefined
81
+ session: ClientSession | undefined,
82
+ timeoutContext: TimeoutContext
77
83
  ): Promise<InsertOneResult> {
78
- const res = await super.execute(server, session);
84
+ const res = await super.execute(server, session, timeoutContext);
79
85
  if (res.code) throw new MongoServerError(res);
80
86
  if (res.writeErrors) {
81
87
  // This should be a WriteError but we can't change it now because of error hierarchy
@@ -123,7 +129,8 @@ export class InsertManyOperation extends AbstractOperation<InsertManyResult> {
123
129
 
124
130
  override async execute(
125
131
  server: Server,
126
- session: ClientSession | undefined
132
+ session: ClientSession | undefined,
133
+ timeoutContext: TimeoutContext
127
134
  ): Promise<InsertManyResult> {
128
135
  const coll = this.collection;
129
136
  const options = { ...this.options, ...this.bsonOptions, readPreference: this.readPreference };
@@ -137,7 +144,7 @@ export class InsertManyOperation extends AbstractOperation<InsertManyResult> {
137
144
  );
138
145
 
139
146
  try {
140
- const res = await bulkWriteOperation.execute(server, session);
147
+ const res = await bulkWriteOperation.execute(server, session, timeoutContext);
141
148
  return {
142
149
  acknowledged: writeConcern?.w !== 0,
143
150
  insertedCount: res.insertedCount,
@@ -2,6 +2,7 @@ import type { Long } from '../bson';
2
2
  import { MongoRuntimeError } from '../error';
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, squashError } from '../utils';
6
7
  import { AbstractOperation, Aspect, defineAspects, type OperationOptions } from './operation';
7
8
 
@@ -29,7 +30,11 @@ export class KillCursorsOperation extends AbstractOperation {
29
30
  return 'killCursors' as const;
30
31
  }
31
32
 
32
- override async execute(server: Server, session: ClientSession | undefined): Promise<void> {
33
+ override async execute(
34
+ server: Server,
35
+ session: ClientSession | undefined,
36
+ timeoutContext: TimeoutContext
37
+ ): Promise<void> {
33
38
  if (server !== this.server) {
34
39
  throw new MongoRuntimeError('Killcursor must run on the same server operation began on');
35
40
  }
@@ -46,7 +51,10 @@ export class KillCursorsOperation extends AbstractOperation {
46
51
  cursors: [this.cursorId]
47
52
  };
48
53
  try {
49
- await server.command(this.ns, killCursorsCommand, { session });
54
+ await server.command(this.ns, killCursorsCommand, {
55
+ session,
56
+ timeoutContext
57
+ });
50
58
  } catch (error) {
51
59
  // The driver should never emit errors from killCursors, this is spec-ed behavior
52
60
  squashError(error);
@@ -1,8 +1,10 @@
1
1
  import type { Binary, Document } from '../bson';
2
2
  import { CursorResponse } from '../cmap/wire_protocol/responses';
3
+ import { type CursorTimeoutContext, type CursorTimeoutMode } from '../cursor/abstract_cursor';
3
4
  import type { Db } from '../db';
4
5
  import type { Server } from '../sdam/server';
5
6
  import type { ClientSession } from '../sessions';
7
+ import { type TimeoutContext } from '../timeout';
6
8
  import { maxWireVersion } from '../utils';
7
9
  import { CommandOperation, type CommandOperationOptions } from './command';
8
10
  import { Aspect, defineAspects } from './operation';
@@ -15,6 +17,11 @@ export interface ListCollectionsOptions extends Omit<CommandOperationOptions, 'w
15
17
  authorizedCollections?: boolean;
16
18
  /** The batchSize for the returned command cursor or if pre 2.8 the systems batch collection */
17
19
  batchSize?: number;
20
+ /** @internal */
21
+ timeoutMode?: CursorTimeoutMode;
22
+
23
+ /** @internal */
24
+ timeoutContext?: CursorTimeoutContext;
18
25
  }
19
26
 
20
27
  /** @internal */
@@ -54,12 +61,14 @@ export class ListCollectionsOperation extends CommandOperation<CursorResponse> {
54
61
 
55
62
  override async execute(
56
63
  server: Server,
57
- session: ClientSession | undefined
64
+ session: ClientSession | undefined,
65
+ timeoutContext: TimeoutContext
58
66
  ): Promise<CursorResponse> {
59
67
  return await super.executeCommand(
60
68
  server,
61
69
  session,
62
70
  this.generateCommand(maxWireVersion(server)),
71
+ timeoutContext,
63
72
  CursorResponse
64
73
  );
65
74
  }
@@ -3,6 +3,7 @@ import type { Db } from '../db';
3
3
  import { type TODO_NODE_3286 } from '../mongo_types';
4
4
  import type { Server } from '../sdam/server';
5
5
  import type { ClientSession } from '../sessions';
6
+ import { type TimeoutContext } from '../timeout';
6
7
  import { maxWireVersion, MongoDBNamespace } from '../utils';
7
8
  import { CommandOperation, type CommandOperationOptions } from './command';
8
9
  import { Aspect, defineAspects } from './operation';
@@ -41,7 +42,8 @@ export class ListDatabasesOperation extends CommandOperation<ListDatabasesResult
41
42
 
42
43
  override async execute(
43
44
  server: Server,
44
- session: ClientSession | undefined
45
+ session: ClientSession | undefined,
46
+ timeoutContext: TimeoutContext
45
47
  ): Promise<ListDatabasesResult> {
46
48
  const cmd: Document = { listDatabases: 1 };
47
49
 
@@ -63,7 +65,12 @@ export class ListDatabasesOperation extends CommandOperation<ListDatabasesResult
63
65
  cmd.comment = this.options.comment;
64
66
  }
65
67
 
66
- return await (super.executeCommand(server, session, cmd) as Promise<TODO_NODE_3286>);
68
+ return await (super.executeCommand(
69
+ server,
70
+ session,
71
+ cmd,
72
+ timeoutContext
73
+ ) as Promise<TODO_NODE_3286>);
67
74
  }
68
75
  }
69
76
 
@@ -2,6 +2,7 @@ import { type BSONSerializeOptions, type Document, resolveBSONOptions } from '..
2
2
  import { ReadPreference, type ReadPreferenceLike } from '../read_preference';
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
 
7
8
  export const Aspect = {
@@ -31,7 +32,13 @@ export interface OperationOptions extends BSONSerializeOptions {
31
32
  bypassPinningCheck?: boolean;
32
33
  omitReadPreference?: boolean;
33
34
 
34
- /** @internal TODO(NODE-5688): make this public */
35
+ /** @internal Hint to `executeOperation` to omit maxTimeMS */
36
+ omitMaxTimeMS?: boolean;
37
+
38
+ /**
39
+ * @experimental
40
+ * Specifies the time an operation will run until it throws a timeout error
41
+ */
35
42
  timeoutMS?: number;
36
43
  }
37
44
 
@@ -57,6 +64,9 @@ export abstract class AbstractOperation<TResult = any> {
57
64
 
58
65
  options: OperationOptions;
59
66
 
67
+ /** Specifies the time an operation will run until it throws a timeout error. */
68
+ timeoutMS?: number;
69
+
60
70
  [kSession]: ClientSession | undefined;
61
71
 
62
72
  static aspects?: Set<symbol>;
@@ -80,7 +90,11 @@ export abstract class AbstractOperation<TResult = any> {
80
90
  Command name should be stateless (should not use 'this' keyword) */
81
91
  abstract get commandName(): string;
82
92
 
83
- abstract execute(server: Server, session: ClientSession | undefined): Promise<TResult>;
93
+ abstract execute(
94
+ server: Server,
95
+ session: ClientSession | undefined,
96
+ timeoutContext: TimeoutContext
97
+ ): Promise<TResult>;
84
98
 
85
99
  hasAspect(aspect: symbol): boolean {
86
100
  const ctor = this.constructor as { aspects?: Set<symbol> };
@@ -2,6 +2,7 @@ import type { Db } from '../db';
2
2
  import { MongoUnexpectedServerResponseError } from '../error';
3
3
  import type { Server } from '../sdam/server';
4
4
  import type { ClientSession } from '../sessions';
5
+ import { type TimeoutContext } from '../timeout';
5
6
  import { CommandOperation, type CommandOperationOptions } from './command';
6
7
 
7
8
  /** @public */
@@ -20,8 +21,12 @@ export class ProfilingLevelOperation extends CommandOperation<string> {
20
21
  return 'profile' as const;
21
22
  }
22
23
 
23
- override async execute(server: Server, session: ClientSession | undefined): Promise<string> {
24
- const doc = await super.executeCommand(server, session, { profile: -1 });
24
+ override async execute(
25
+ server: Server,
26
+ session: ClientSession | undefined,
27
+ timeoutContext: TimeoutContext
28
+ ): Promise<string> {
29
+ const doc = await super.executeCommand(server, session, { profile: -1 }, timeoutContext);
25
30
  if (doc.ok === 1) {
26
31
  const was = doc.was;
27
32
  if (was === 0) return 'off';
@@ -1,6 +1,7 @@
1
1
  import type { Db } from '../db';
2
2
  import type { Server } from '../sdam/server';
3
3
  import type { ClientSession } from '../sessions';
4
+ import { type TimeoutContext } from '../timeout';
4
5
  import { CommandOperation, type CommandOperationOptions } from './command';
5
6
  import { Aspect, defineAspects } from './operation';
6
7
 
@@ -22,8 +23,12 @@ export class RemoveUserOperation extends CommandOperation<boolean> {
22
23
  return 'dropUser' as const;
23
24
  }
24
25
 
25
- override async execute(server: Server, session: ClientSession | undefined): Promise<boolean> {
26
- await super.executeCommand(server, session, { dropUser: this.username });
26
+ override async execute(
27
+ server: Server,
28
+ session: ClientSession | undefined,
29
+ timeoutContext: TimeoutContext
30
+ ): Promise<boolean> {
31
+ await super.executeCommand(server, session, { dropUser: this.username }, timeoutContext);
27
32
  return true;
28
33
  }
29
34
  }
@@ -2,6 +2,7 @@ import type { Document } from '../bson';
2
2
  import { 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 { MongoDBNamespace } from '../utils';
6
7
  import { CommandOperation, type CommandOperationOptions } from './command';
7
8
  import { Aspect, defineAspects } from './operation';
@@ -29,7 +30,11 @@ export class RenameOperation extends CommandOperation<Document> {
29
30
  return 'renameCollection' as const;
30
31
  }
31
32
 
32
- override async execute(server: Server, session: ClientSession | undefined): Promise<Collection> {
33
+ override async execute(
34
+ server: Server,
35
+ session: ClientSession | undefined,
36
+ timeoutContext: TimeoutContext
37
+ ): Promise<Collection> {
33
38
  // Build the command
34
39
  const renameCollection = this.collection.namespace;
35
40
  const toCollection = this.collection.s.namespace.withCollection(this.newName).toString();
@@ -42,7 +47,7 @@ export class RenameOperation extends CommandOperation<Document> {
42
47
  dropTarget: dropTarget
43
48
  };
44
49
 
45
- await super.executeCommand(server, session, command);
50
+ await super.executeCommand(server, session, command, timeoutContext);
46
51
  return new Collection(this.collection.s.db, this.newName, this.collection.s.options);
47
52
  }
48
53
  }