mongodb 6.10.0-dev.20241106.sha.dc3fe957 → 6.10.0-dev.20241107.sha.e5582ed7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (203) hide show
  1. package/lib/admin.js +3 -2
  2. package/lib/admin.js.map +1 -1
  3. package/lib/beta.d.ts +558 -38
  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/connection.js +78 -6
  15. package/lib/cmap/connection.js.map +1 -1
  16. package/lib/cmap/connection_pool.js +14 -9
  17. package/lib/cmap/connection_pool.js.map +1 -1
  18. package/lib/cmap/wire_protocol/on_data.js +5 -1
  19. package/lib/cmap/wire_protocol/on_data.js.map +1 -1
  20. package/lib/cmap/wire_protocol/responses.js +30 -0
  21. package/lib/cmap/wire_protocol/responses.js.map +1 -1
  22. package/lib/collection.js +62 -3
  23. package/lib/collection.js.map +1 -1
  24. package/lib/connection_string.js +2 -0
  25. package/lib/connection_string.js.map +1 -1
  26. package/lib/cursor/abstract_cursor.js +218 -38
  27. package/lib/cursor/abstract_cursor.js.map +1 -1
  28. package/lib/cursor/aggregation_cursor.js +29 -7
  29. package/lib/cursor/aggregation_cursor.js.map +1 -1
  30. package/lib/cursor/change_stream_cursor.js +2 -2
  31. package/lib/cursor/change_stream_cursor.js.map +1 -1
  32. package/lib/cursor/client_bulk_write_cursor.js +1 -1
  33. package/lib/cursor/client_bulk_write_cursor.js.map +1 -1
  34. package/lib/cursor/find_cursor.js +18 -8
  35. package/lib/cursor/find_cursor.js.map +1 -1
  36. package/lib/cursor/list_collections_cursor.js +1 -1
  37. package/lib/cursor/list_collections_cursor.js.map +1 -1
  38. package/lib/cursor/list_indexes_cursor.js +1 -1
  39. package/lib/cursor/list_indexes_cursor.js.map +1 -1
  40. package/lib/cursor/run_command_cursor.js +6 -4
  41. package/lib/cursor/run_command_cursor.js.map +1 -1
  42. package/lib/db.js +63 -3
  43. package/lib/db.js.map +1 -1
  44. package/lib/error.js +27 -2
  45. package/lib/error.js.map +1 -1
  46. package/lib/explain.js +57 -1
  47. package/lib/explain.js.map +1 -1
  48. package/lib/gridfs/download.js +31 -3
  49. package/lib/gridfs/download.js.map +1 -1
  50. package/lib/gridfs/index.js +49 -14
  51. package/lib/gridfs/index.js.map +1 -1
  52. package/lib/gridfs/upload.js +80 -22
  53. package/lib/gridfs/upload.js.map +1 -1
  54. package/lib/index.js +9 -5
  55. package/lib/index.js.map +1 -1
  56. package/lib/mongo_client.js +70 -1
  57. package/lib/mongo_client.js.map +1 -1
  58. package/lib/operations/aggregate.js +2 -2
  59. package/lib/operations/aggregate.js.map +1 -1
  60. package/lib/operations/bulk_write.js +7 -2
  61. package/lib/operations/bulk_write.js.map +1 -1
  62. package/lib/operations/client_bulk_write/client_bulk_write.js +3 -3
  63. package/lib/operations/client_bulk_write/client_bulk_write.js.map +1 -1
  64. package/lib/operations/client_bulk_write/executor.js +14 -3
  65. package/lib/operations/client_bulk_write/executor.js.map +1 -1
  66. package/lib/operations/command.js +5 -2
  67. package/lib/operations/command.js.map +1 -1
  68. package/lib/operations/count.js +2 -2
  69. package/lib/operations/count.js.map +1 -1
  70. package/lib/operations/create_collection.js +8 -7
  71. package/lib/operations/create_collection.js.map +1 -1
  72. package/lib/operations/delete.js +6 -6
  73. package/lib/operations/delete.js.map +1 -1
  74. package/lib/operations/distinct.js +2 -2
  75. package/lib/operations/distinct.js.map +1 -1
  76. package/lib/operations/drop.js +8 -8
  77. package/lib/operations/drop.js.map +1 -1
  78. package/lib/operations/estimated_document_count.js +2 -2
  79. package/lib/operations/estimated_document_count.js.map +1 -1
  80. package/lib/operations/execute_operation.js +16 -10
  81. package/lib/operations/execute_operation.js.map +1 -1
  82. package/lib/operations/find.js +6 -3
  83. package/lib/operations/find.js.map +1 -1
  84. package/lib/operations/find_and_modify.js +2 -2
  85. package/lib/operations/find_and_modify.js.map +1 -1
  86. package/lib/operations/get_more.js +2 -1
  87. package/lib/operations/get_more.js.map +1 -1
  88. package/lib/operations/indexes.js +6 -6
  89. package/lib/operations/indexes.js.map +1 -1
  90. package/lib/operations/insert.js +6 -6
  91. package/lib/operations/insert.js.map +1 -1
  92. package/lib/operations/kill_cursors.js +5 -2
  93. package/lib/operations/kill_cursors.js.map +1 -1
  94. package/lib/operations/list_collections.js +2 -2
  95. package/lib/operations/list_collections.js.map +1 -1
  96. package/lib/operations/list_databases.js +2 -2
  97. package/lib/operations/list_databases.js.map +1 -1
  98. package/lib/operations/operation.js.map +1 -1
  99. package/lib/operations/profiling_level.js +2 -2
  100. package/lib/operations/profiling_level.js.map +1 -1
  101. package/lib/operations/remove_user.js +2 -2
  102. package/lib/operations/remove_user.js.map +1 -1
  103. package/lib/operations/rename.js +2 -2
  104. package/lib/operations/rename.js.map +1 -1
  105. package/lib/operations/run_command.js +6 -4
  106. package/lib/operations/run_command.js.map +1 -1
  107. package/lib/operations/search_indexes/create.js +5 -2
  108. package/lib/operations/search_indexes/create.js.map +1 -1
  109. package/lib/operations/search_indexes/drop.js +2 -2
  110. package/lib/operations/search_indexes/drop.js.map +1 -1
  111. package/lib/operations/search_indexes/update.js +2 -2
  112. package/lib/operations/search_indexes/update.js.map +1 -1
  113. package/lib/operations/set_profiling_level.js +2 -2
  114. package/lib/operations/set_profiling_level.js.map +1 -1
  115. package/lib/operations/stats.js +2 -2
  116. package/lib/operations/stats.js.map +1 -1
  117. package/lib/operations/update.js +8 -8
  118. package/lib/operations/update.js.map +1 -1
  119. package/lib/operations/validate_collection.js +2 -2
  120. package/lib/operations/validate_collection.js.map +1 -1
  121. package/lib/sdam/server.js +4 -1
  122. package/lib/sdam/server.js.map +1 -1
  123. package/lib/sdam/server_description.js +2 -0
  124. package/lib/sdam/server_description.js.map +1 -1
  125. package/lib/sdam/topology.js +38 -11
  126. package/lib/sdam/topology.js.map +1 -1
  127. package/lib/sessions.js +145 -74
  128. package/lib/sessions.js.map +1 -1
  129. package/lib/timeout.js +217 -16
  130. package/lib/timeout.js.map +1 -1
  131. package/lib/utils.js +31 -17
  132. package/lib/utils.js.map +1 -1
  133. package/lib/write_concern.js.map +1 -1
  134. package/mongodb.d.ts +558 -38
  135. package/package.json +2 -2
  136. package/src/admin.ts +6 -2
  137. package/src/bulk/common.ts +17 -5
  138. package/src/change_stream.ts +127 -52
  139. package/src/client-side-encryption/auto_encrypter.ts +12 -5
  140. package/src/client-side-encryption/client_encryption.ts +103 -20
  141. package/src/client-side-encryption/state_machine.ts +66 -32
  142. package/src/cmap/connection.ts +105 -8
  143. package/src/cmap/connection_pool.ts +14 -14
  144. package/src/cmap/wire_protocol/on_data.ts +11 -1
  145. package/src/cmap/wire_protocol/responses.ts +35 -1
  146. package/src/collection.ts +81 -9
  147. package/src/connection_string.ts +2 -0
  148. package/src/cursor/abstract_cursor.ts +286 -39
  149. package/src/cursor/aggregation_cursor.ts +54 -8
  150. package/src/cursor/change_stream_cursor.ts +6 -2
  151. package/src/cursor/client_bulk_write_cursor.ts +6 -2
  152. package/src/cursor/find_cursor.ts +40 -9
  153. package/src/cursor/list_collections_cursor.ts +1 -1
  154. package/src/cursor/list_indexes_cursor.ts +1 -1
  155. package/src/cursor/run_command_cursor.ts +50 -5
  156. package/src/db.ts +75 -7
  157. package/src/error.ts +26 -1
  158. package/src/explain.ts +85 -0
  159. package/src/gridfs/download.ts +43 -4
  160. package/src/gridfs/index.ts +64 -16
  161. package/src/gridfs/upload.ts +152 -45
  162. package/src/index.ts +26 -4
  163. package/src/mongo_client.ts +75 -3
  164. package/src/operations/aggregate.ts +10 -2
  165. package/src/operations/bulk_write.ts +9 -2
  166. package/src/operations/client_bulk_write/client_bulk_write.ts +11 -3
  167. package/src/operations/client_bulk_write/executor.ts +15 -3
  168. package/src/operations/command.ts +18 -8
  169. package/src/operations/count.ts +10 -3
  170. package/src/operations/create_collection.ts +14 -7
  171. package/src/operations/delete.ts +15 -6
  172. package/src/operations/distinct.ts +7 -2
  173. package/src/operations/drop.ts +18 -8
  174. package/src/operations/estimated_document_count.ts +7 -2
  175. package/src/operations/execute_operation.ts +22 -13
  176. package/src/operations/find.ts +17 -5
  177. package/src/operations/find_and_modify.ts +7 -2
  178. package/src/operations/get_more.ts +4 -1
  179. package/src/operations/indexes.ts +20 -7
  180. package/src/operations/insert.ts +13 -6
  181. package/src/operations/kill_cursors.ts +10 -2
  182. package/src/operations/list_collections.ts +10 -1
  183. package/src/operations/list_databases.ts +9 -2
  184. package/src/operations/operation.ts +16 -2
  185. package/src/operations/profiling_level.ts +7 -2
  186. package/src/operations/remove_user.ts +7 -2
  187. package/src/operations/rename.ts +7 -2
  188. package/src/operations/run_command.ts +23 -4
  189. package/src/operations/search_indexes/create.ts +10 -2
  190. package/src/operations/search_indexes/drop.ts +7 -2
  191. package/src/operations/search_indexes/update.ts +7 -2
  192. package/src/operations/set_profiling_level.ts +4 -2
  193. package/src/operations/stats.ts +7 -2
  194. package/src/operations/update.ts +16 -8
  195. package/src/operations/validate_collection.ts +7 -2
  196. package/src/sdam/server.ts +14 -4
  197. package/src/sdam/server_description.ts +4 -0
  198. package/src/sdam/topology.ts +43 -18
  199. package/src/sessions.ts +193 -89
  200. package/src/timeout.ts +310 -23
  201. package/src/transactions.ts +1 -1
  202. package/src/utils.ts +42 -28
  203. package/src/write_concern.ts +6 -3
@@ -2,6 +2,7 @@ import type { Document } from '../bson';
2
2
  import type { Db } from '../db';
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
 
@@ -24,13 +25,17 @@ export class DbStatsOperation extends CommandOperation<Document> {
24
25
  return 'dbStats' as const;
25
26
  }
26
27
 
27
- override async execute(server: Server, session: ClientSession | undefined): Promise<Document> {
28
+ override async execute(
29
+ server: Server,
30
+ session: ClientSession | undefined,
31
+ timeoutContext: TimeoutContext
32
+ ): Promise<Document> {
28
33
  const command: Document = { dbStats: true };
29
34
  if (this.options.scale != null) {
30
35
  command.scale = this.options.scale;
31
36
  }
32
37
 
33
- return await super.executeCommand(server, session, command);
38
+ return await super.executeCommand(server, session, command, timeoutContext);
34
39
  }
35
40
  }
36
41
 
@@ -4,6 +4,7 @@ import { MongoCompatibilityError, MongoInvalidArgumentError, MongoServerError }
4
4
  import type { InferIdType, 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 { hasAtomicOperators, type MongoDBNamespace } from '../utils';
8
9
  import { type CollationOptions, CommandOperation, type CommandOperationOptions } from './command';
9
10
  import { Aspect, defineAspects, type Hint } from './operation';
@@ -91,7 +92,11 @@ export class UpdateOperation extends CommandOperation<Document> {
91
92
  return this.statements.every(op => op.multi == null || op.multi === false);
92
93
  }
93
94
 
94
- override async execute(server: Server, session: ClientSession | undefined): Promise<Document> {
95
+ override async execute(
96
+ server: Server,
97
+ session: ClientSession | undefined,
98
+ timeoutContext: TimeoutContext
99
+ ): Promise<Document> {
95
100
  const options = this.options ?? {};
96
101
  const ordered = typeof options.ordered === 'boolean' ? options.ordered : true;
97
102
  const command: Document = {
@@ -122,7 +127,7 @@ export class UpdateOperation extends CommandOperation<Document> {
122
127
  }
123
128
  }
124
129
 
125
- const res = await super.executeCommand(server, session, command);
130
+ const res = await super.executeCommand(server, session, command, timeoutContext);
126
131
  return res;
127
132
  }
128
133
  }
@@ -143,9 +148,10 @@ export class UpdateOneOperation extends UpdateOperation {
143
148
 
144
149
  override async execute(
145
150
  server: Server,
146
- session: ClientSession | undefined
151
+ session: ClientSession | undefined,
152
+ timeoutContext: TimeoutContext
147
153
  ): Promise<UpdateResult> {
148
- const res: TODO_NODE_3286 = await super.execute(server, session);
154
+ const res: TODO_NODE_3286 = await super.execute(server, session, timeoutContext);
149
155
  if (this.explain != null) return res;
150
156
  if (res.code) throw new MongoServerError(res);
151
157
  if (res.writeErrors) throw new MongoServerError(res.writeErrors[0]);
@@ -177,9 +183,10 @@ export class UpdateManyOperation extends UpdateOperation {
177
183
 
178
184
  override async execute(
179
185
  server: Server,
180
- session: ClientSession | undefined
186
+ session: ClientSession | undefined,
187
+ timeoutContext: TimeoutContext
181
188
  ): Promise<UpdateResult> {
182
- const res: TODO_NODE_3286 = await super.execute(server, session);
189
+ const res: TODO_NODE_3286 = await super.execute(server, session, timeoutContext);
183
190
  if (this.explain != null) return res;
184
191
  if (res.code) throw new MongoServerError(res);
185
192
  if (res.writeErrors) throw new MongoServerError(res.writeErrors[0]);
@@ -230,9 +237,10 @@ export class ReplaceOneOperation extends UpdateOperation {
230
237
 
231
238
  override async execute(
232
239
  server: Server,
233
- session: ClientSession | undefined
240
+ session: ClientSession | undefined,
241
+ timeoutContext: TimeoutContext
234
242
  ): Promise<UpdateResult> {
235
- const res: TODO_NODE_3286 = await super.execute(server, session);
243
+ const res: TODO_NODE_3286 = await super.execute(server, session, timeoutContext);
236
244
  if (this.explain != null) return res;
237
245
  if (res.code) throw new MongoServerError(res);
238
246
  if (res.writeErrors) throw new MongoServerError(res.writeErrors[0]);
@@ -3,6 +3,7 @@ import type { Document } from '../bson';
3
3
  import { MongoUnexpectedServerResponseError } 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
 
8
9
  /** @public */
@@ -37,10 +38,14 @@ export class ValidateCollectionOperation extends CommandOperation<Document> {
37
38
  return 'validate' as const;
38
39
  }
39
40
 
40
- override async execute(server: Server, session: ClientSession | undefined): Promise<Document> {
41
+ override async execute(
42
+ server: Server,
43
+ session: ClientSession | undefined,
44
+ timeoutContext: TimeoutContext
45
+ ): Promise<Document> {
41
46
  const collectionName = this.collectionName;
42
47
 
43
- const doc = await super.executeCommand(server, session, this.command);
48
+ const doc = await super.executeCommand(server, session, this.command, timeoutContext);
44
49
  if (doc.result != null && typeof doc.result !== 'string')
45
50
  throw new MongoUnexpectedServerResponseError('Error with validation data');
46
51
  if (doc.result != null && doc.result.match(/exception|corrupt/) != null)
@@ -40,6 +40,7 @@ import type { ServerApi } from '../mongo_client';
40
40
  import { TypedEventEmitter } from '../mongo_types';
41
41
  import type { GetMoreOptions } from '../operations/get_more';
42
42
  import type { ClientSession } from '../sessions';
43
+ import { type TimeoutContext } from '../timeout';
43
44
  import { isTransactionCommand } from '../transactions';
44
45
  import {
45
46
  type EventEmitterWithState,
@@ -104,6 +105,11 @@ export type ServerEvents = {
104
105
  } & ConnectionPoolEvents &
105
106
  EventEmitterWithState;
106
107
 
108
+ /** @internal */
109
+ export type ServerCommandOptions = Omit<CommandOptions, 'timeoutContext' | 'socketTimeoutMS'> & {
110
+ timeoutContext: TimeoutContext;
111
+ };
112
+
107
113
  /** @internal */
108
114
  export class Server extends TypedEventEmitter<ServerEvents> {
109
115
  /** @internal */
@@ -267,20 +273,20 @@ export class Server extends TypedEventEmitter<ServerEvents> {
267
273
  public async command<T extends MongoDBResponseConstructor>(
268
274
  ns: MongoDBNamespace,
269
275
  command: Document,
270
- options: CommandOptions | undefined,
276
+ options: ServerCommandOptions,
271
277
  responseType: T | undefined
272
278
  ): Promise<typeof responseType extends undefined ? Document : InstanceType<T>>;
273
279
 
274
280
  public async command(
275
281
  ns: MongoDBNamespace,
276
282
  command: Document,
277
- options?: CommandOptions
283
+ options: ServerCommandOptions
278
284
  ): Promise<Document>;
279
285
 
280
286
  public async command(
281
287
  ns: MongoDBNamespace,
282
288
  cmd: Document,
283
- options: CommandOptions,
289
+ options: ServerCommandOptions,
284
290
  responseType?: MongoDBResponseConstructor
285
291
  ): Promise<Document> {
286
292
  if (ns.db == null || typeof ns === 'string') {
@@ -305,13 +311,17 @@ export class Server extends TypedEventEmitter<ServerEvents> {
305
311
  delete finalOptions.readPreference;
306
312
  }
307
313
 
314
+ if (this.description.iscryptd) {
315
+ finalOptions.omitMaxTimeMS = true;
316
+ }
317
+
308
318
  const session = finalOptions.session;
309
319
  let conn = session?.pinnedConnection;
310
320
 
311
321
  this.incrementOperationCount();
312
322
  if (conn == null) {
313
323
  try {
314
- conn = await this.pool.checkOut();
324
+ conn = await this.pool.checkOut(options);
315
325
  if (this.loadBalanced && isPinnableCommand(cmd, session)) {
316
326
  session?.pin(conn);
317
327
  }
@@ -75,6 +75,8 @@ export class ServerDescription {
75
75
  maxWriteBatchSize: number | null;
76
76
  /** The max bson object size. */
77
77
  maxBsonObjectSize: number | null;
78
+ /** Indicates server is a mongocryptd instance. */
79
+ iscryptd: boolean;
78
80
 
79
81
  // NOTE: does this belong here? It seems we should gossip the cluster time at the CMAP level
80
82
  $clusterTime?: ClusterTime;
@@ -123,6 +125,7 @@ export class ServerDescription {
123
125
  this.primary = hello?.primary ?? null;
124
126
  this.me = hello?.me?.toLowerCase() ?? null;
125
127
  this.$clusterTime = hello?.$clusterTime ?? null;
128
+ this.iscryptd = Boolean(hello?.iscryptd);
126
129
  }
127
130
 
128
131
  get hostAddress(): HostAddress {
@@ -176,6 +179,7 @@ export class ServerDescription {
176
179
 
177
180
  return (
178
181
  other != null &&
182
+ other.iscryptd === this.iscryptd &&
179
183
  errorStrictEqual(this.error, other.error) &&
180
184
  this.type === other.type &&
181
185
  this.minWireVersion === other.minWireVersion &&
@@ -24,6 +24,7 @@ import {
24
24
  type MongoDriverError,
25
25
  MongoError,
26
26
  MongoErrorLabel,
27
+ MongoOperationTimeoutError,
27
28
  MongoRuntimeError,
28
29
  MongoServerSelectionError,
29
30
  MongoTopologyClosedError
@@ -33,7 +34,7 @@ import { MongoLoggableComponent, type MongoLogger, SeverityLevel } from '../mong
33
34
  import { TypedEventEmitter } from '../mongo_types';
34
35
  import { ReadPreference, type ReadPreferenceLike } from '../read_preference';
35
36
  import type { ClientSession } from '../sessions';
36
- import { Timeout, TimeoutError } from '../timeout';
37
+ import { Timeout, TimeoutContext, TimeoutError } from '../timeout';
37
38
  import type { Transaction } from '../transactions';
38
39
  import {
39
40
  type Callback,
@@ -107,7 +108,6 @@ export interface ServerSelectionRequest {
107
108
  resolve: (server: Server) => void;
108
109
  reject: (error: MongoError) => void;
109
110
  [kCancelled]?: boolean;
110
- timeout: Timeout;
111
111
  operationName: string;
112
112
  waitingLogged: boolean;
113
113
  previousServer?: ServerDescription;
@@ -178,8 +178,11 @@ export interface SelectServerOptions {
178
178
  session?: ClientSession;
179
179
  operationName: string;
180
180
  previousServer?: ServerDescription;
181
- /** @internal*/
182
- timeout?: Timeout;
181
+ /**
182
+ * @internal
183
+ * TODO(NODE-6496): Make this required by making ChangeStream use LegacyTimeoutContext
184
+ * */
185
+ timeoutContext?: TimeoutContext;
183
186
  }
184
187
 
185
188
  /** @public */
@@ -457,17 +460,28 @@ export class Topology extends TypedEventEmitter<TopologyEvents> {
457
460
  }
458
461
  }
459
462
 
463
+ const serverSelectionTimeoutMS = this.client.s.options.serverSelectionTimeoutMS;
460
464
  const readPreference = options.readPreference ?? ReadPreference.primary;
461
- const selectServerOptions = { operationName: 'ping', ...options };
465
+ const timeoutContext = TimeoutContext.create({
466
+ // TODO(NODE-6448): auto-connect ignores timeoutMS; potential future feature
467
+ timeoutMS: undefined,
468
+ serverSelectionTimeoutMS,
469
+ waitQueueTimeoutMS: this.client.s.options.waitQueueTimeoutMS
470
+ });
471
+ const selectServerOptions = {
472
+ operationName: 'ping',
473
+ ...options,
474
+ timeoutContext
475
+ };
476
+
462
477
  try {
463
478
  const server = await this.selectServer(
464
479
  readPreferenceServerSelector(readPreference),
465
480
  selectServerOptions
466
481
  );
467
-
468
482
  const skipPingOnConnect = this.s.options[Symbol.for('@@mdb.skipPingOnConnect')] === true;
469
- if (!skipPingOnConnect && server && this.s.credentials) {
470
- await server.command(ns('admin.$cmd'), { ping: 1 }, {});
483
+ if (!skipPingOnConnect && this.s.credentials) {
484
+ await server.command(ns('admin.$cmd'), { ping: 1 }, { timeoutContext });
471
485
  stateTransition(this, STATE_CONNECTED);
472
486
  this.emit(Topology.OPEN, this);
473
487
  this.emit(Topology.CONNECT, this);
@@ -556,6 +570,11 @@ export class Topology extends TypedEventEmitter<TopologyEvents> {
556
570
  new ServerSelectionStartedEvent(selector, this.description, options.operationName)
557
571
  );
558
572
  }
573
+ let timeout;
574
+ if (options.timeoutContext) timeout = options.timeoutContext.serverSelectionTimeout;
575
+ else {
576
+ timeout = Timeout.expires(options.serverSelectionTimeoutMS ?? 0);
577
+ }
559
578
 
560
579
  const isSharded = this.description.type === TopologyType.Sharded;
561
580
  const session = options.session;
@@ -578,11 +597,12 @@ export class Topology extends TypedEventEmitter<TopologyEvents> {
578
597
  )
579
598
  );
580
599
  }
600
+ if (options.timeoutContext?.clearServerSelectionTimeout) timeout?.clear();
581
601
  return transaction.server;
582
602
  }
583
603
 
584
604
  const { promise: serverPromise, resolve, reject } = promiseWithResolvers<Server>();
585
- const timeout = Timeout.expires(options.serverSelectionTimeoutMS ?? 0);
605
+
586
606
  const waitQueueMember: ServerSelectionRequest = {
587
607
  serverSelector,
588
608
  topologyDescription: this.description,
@@ -590,7 +610,6 @@ export class Topology extends TypedEventEmitter<TopologyEvents> {
590
610
  transaction,
591
611
  resolve,
592
612
  reject,
593
- timeout,
594
613
  startTime: now(),
595
614
  operationName: options.operationName,
596
615
  waitingLogged: false,
@@ -601,14 +620,18 @@ export class Topology extends TypedEventEmitter<TopologyEvents> {
601
620
  processWaitQueue(this);
602
621
 
603
622
  try {
604
- return await Promise.race([serverPromise, waitQueueMember.timeout]);
623
+ timeout?.throwIfExpired();
624
+ const server = await (timeout ? Promise.race([serverPromise, timeout]) : serverPromise);
625
+ if (options.timeoutContext?.csotEnabled() && server.description.minRoundTripTime !== 0) {
626
+ options.timeoutContext.minRoundTripTime = server.description.minRoundTripTime;
627
+ }
628
+ return server;
605
629
  } catch (error) {
606
630
  if (TimeoutError.is(error)) {
607
631
  // Timeout
608
632
  waitQueueMember[kCancelled] = true;
609
- timeout.clear();
610
633
  const timeoutError = new MongoServerSelectionError(
611
- `Server selection timed out after ${options.serverSelectionTimeoutMS} ms`,
634
+ `Server selection timed out after ${timeout?.duration} ms`,
612
635
  this.description
613
636
  );
614
637
  if (
@@ -628,10 +651,17 @@ export class Topology extends TypedEventEmitter<TopologyEvents> {
628
651
  );
629
652
  }
630
653
 
654
+ if (options.timeoutContext?.csotEnabled()) {
655
+ throw new MongoOperationTimeoutError('Timed out during server selection', {
656
+ cause: timeoutError
657
+ });
658
+ }
631
659
  throw timeoutError;
632
660
  }
633
661
  // Other server selection error
634
662
  throw error;
663
+ } finally {
664
+ if (options.timeoutContext?.clearServerSelectionTimeout) timeout?.clear();
635
665
  }
636
666
  }
637
667
  /**
@@ -889,8 +919,6 @@ function drainWaitQueue(queue: List<ServerSelectionRequest>, drainError: MongoDr
889
919
  continue;
890
920
  }
891
921
 
892
- waitQueueMember.timeout.clear();
893
-
894
922
  if (!waitQueueMember[kCancelled]) {
895
923
  if (
896
924
  waitQueueMember.mongoLogger?.willLog(
@@ -944,7 +972,6 @@ function processWaitQueue(topology: Topology) {
944
972
  )
945
973
  : serverDescriptions;
946
974
  } catch (selectorError) {
947
- waitQueueMember.timeout.clear();
948
975
  if (
949
976
  topology.client.mongoLogger?.willLog(
950
977
  MongoLoggableComponent.SERVER_SELECTION,
@@ -1032,8 +1059,6 @@ function processWaitQueue(topology: Topology) {
1032
1059
  transaction.pinServer(selectedServer);
1033
1060
  }
1034
1061
 
1035
- waitQueueMember.timeout.clear();
1036
-
1037
1062
  if (
1038
1063
  topology.client.mongoLogger?.willLog(
1039
1064
  MongoLoggableComponent.SERVER_SELECTION,