mongodb 6.18.0-dev.20250802.sha.be7f808c → 6.18.0-dev.20250806.sha.e628296a

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 (62) hide show
  1. package/lib/beta.d.ts +4 -1
  2. package/lib/cmap/connection.js.map +1 -1
  3. package/lib/cursor/aggregation_cursor.js +2 -1
  4. package/lib/cursor/aggregation_cursor.js.map +1 -1
  5. package/lib/cursor/explainable_cursor.js +36 -0
  6. package/lib/cursor/explainable_cursor.js.map +1 -0
  7. package/lib/cursor/find_cursor.js +2 -1
  8. package/lib/cursor/find_cursor.js.map +1 -1
  9. package/lib/explain.js +1 -33
  10. package/lib/explain.js.map +1 -1
  11. package/lib/index.js +6 -6
  12. package/lib/index.js.map +1 -1
  13. package/lib/operations/aggregate.js +10 -8
  14. package/lib/operations/aggregate.js.map +1 -1
  15. package/lib/operations/command.js +68 -6
  16. package/lib/operations/command.js.map +1 -1
  17. package/lib/operations/drop.js +2 -1
  18. package/lib/operations/drop.js.map +1 -1
  19. package/lib/operations/execute_operation.js +15 -2
  20. package/lib/operations/execute_operation.js.map +1 -1
  21. package/lib/operations/find.js +13 -24
  22. package/lib/operations/find.js.map +1 -1
  23. package/lib/operations/get_more.js +11 -12
  24. package/lib/operations/get_more.js.map +1 -1
  25. package/lib/operations/indexes.js +8 -4
  26. package/lib/operations/indexes.js.map +1 -1
  27. package/lib/operations/insert.js +18 -3
  28. package/lib/operations/insert.js.map +1 -1
  29. package/lib/operations/kill_cursors.js +14 -16
  30. package/lib/operations/kill_cursors.js.map +1 -1
  31. package/lib/operations/list_collections.js +8 -7
  32. package/lib/operations/list_collections.js.map +1 -1
  33. package/lib/operations/operation.js +39 -2
  34. package/lib/operations/operation.js.map +1 -1
  35. package/lib/operations/search_indexes/drop.js +17 -10
  36. package/lib/operations/search_indexes/drop.js.map +1 -1
  37. package/lib/sdam/server.js +86 -7
  38. package/lib/sdam/server.js.map +1 -1
  39. package/lib/sdam/topology.js +3 -2
  40. package/lib/sdam/topology.js.map +1 -1
  41. package/mongodb.d.ts +4 -1
  42. package/package.json +1 -1
  43. package/src/cmap/connection.ts +0 -1
  44. package/src/cursor/aggregation_cursor.ts +1 -1
  45. package/src/cursor/explainable_cursor.ts +51 -0
  46. package/src/cursor/find_cursor.ts +1 -1
  47. package/src/explain.ts +0 -49
  48. package/src/index.ts +8 -3
  49. package/src/operations/aggregate.ts +21 -22
  50. package/src/operations/command.ts +90 -9
  51. package/src/operations/drop.ts +2 -1
  52. package/src/operations/execute_operation.ts +20 -3
  53. package/src/operations/find.ts +28 -49
  54. package/src/operations/get_more.ts +18 -20
  55. package/src/operations/indexes.ts +13 -8
  56. package/src/operations/insert.ts +22 -9
  57. package/src/operations/kill_cursors.ts +22 -23
  58. package/src/operations/list_collections.ts +15 -23
  59. package/src/operations/operation.ts +60 -4
  60. package/src/operations/search_indexes/drop.ts +25 -16
  61. package/src/sdam/server.ts +98 -8
  62. package/src/sdam/topology.ts +4 -3
@@ -1,10 +1,12 @@
1
1
  import type { Long } from '../bson';
2
- import { MongoRuntimeError } from '../error';
3
- import type { Server } from '../sdam/server';
2
+ import { type Connection } from '../cmap/connection';
3
+ import { MongoDBResponse } from '../cmap/wire_protocol/responses';
4
+ import { type MongoError, MongoRuntimeError } from '../error';
5
+ import type { Server, ServerCommandOptions } from '../sdam/server';
4
6
  import type { ClientSession } from '../sessions';
5
7
  import { type TimeoutContext } from '../timeout';
6
- import { type MongoDBNamespace, squashError } from '../utils';
7
- import { AbstractOperation, Aspect, defineAspects, type OperationOptions } from './operation';
8
+ import { type MongoDBNamespace } from '../utils';
9
+ import { Aspect, defineAspects, ModernizedOperation, type OperationOptions } from './operation';
8
10
 
9
11
  /**
10
12
  * https://www.mongodb.com/docs/manual/reference/command/killCursors/
@@ -16,7 +18,8 @@ interface KillCursorsCommand {
16
18
  comment?: unknown;
17
19
  }
18
20
 
19
- export class KillCursorsOperation extends AbstractOperation {
21
+ export class KillCursorsOperation extends ModernizedOperation<void> {
22
+ override SERVER_COMMAND_RESPONSE_TYPE = MongoDBResponse;
20
23
  cursorId: Long;
21
24
 
22
25
  constructor(cursorId: Long, ns: MongoDBNamespace, server: Server, options: OperationOptions) {
@@ -30,15 +33,7 @@ export class KillCursorsOperation extends AbstractOperation {
30
33
  return 'killCursors' as const;
31
34
  }
32
35
 
33
- override async execute(
34
- server: Server,
35
- session: ClientSession | undefined,
36
- timeoutContext: TimeoutContext
37
- ): Promise<void> {
38
- if (server !== this.server) {
39
- throw new MongoRuntimeError('Killcursor must run on the same server operation began on');
40
- }
41
-
36
+ override buildCommand(_connection: Connection, _session?: ClientSession): KillCursorsCommand {
42
37
  const killCursors = this.ns.collection;
43
38
  if (killCursors == null) {
44
39
  // Cursors should have adopted the namespace returned by MongoDB
@@ -50,15 +45,19 @@ export class KillCursorsOperation extends AbstractOperation {
50
45
  killCursors,
51
46
  cursors: [this.cursorId]
52
47
  };
53
- try {
54
- await server.command(this.ns, killCursorsCommand, {
55
- session,
56
- timeoutContext
57
- });
58
- } catch (error) {
59
- // The driver should never emit errors from killCursors, this is spec-ed behavior
60
- squashError(error);
61
- }
48
+
49
+ return killCursorsCommand;
50
+ }
51
+
52
+ override buildOptions(timeoutContext: TimeoutContext): ServerCommandOptions {
53
+ return {
54
+ session: this.session,
55
+ timeoutContext
56
+ };
57
+ }
58
+
59
+ override handleError(_error: MongoError): void {
60
+ // The driver should never emit errors from killCursors, this is spec-ed behavior
62
61
  }
63
62
  }
64
63
 
@@ -1,13 +1,11 @@
1
+ import { type Connection } from '..';
1
2
  import type { Binary, Document } from '../bson';
2
- import { CursorResponse } from '../cmap/wire_protocol/responses';
3
+ import { CursorResponse, ExplainedCursorResponse } from '../cmap/wire_protocol/responses';
3
4
  import { type CursorTimeoutContext, type CursorTimeoutMode } from '../cursor/abstract_cursor';
4
5
  import type { Db } from '../db';
5
6
  import { type Abortable } from '../mongo_types';
6
- import type { Server } from '../sdam/server';
7
- import type { ClientSession } from '../sessions';
8
- import { type TimeoutContext } from '../timeout';
9
7
  import { maxWireVersion } from '../utils';
10
- import { CommandOperation, type CommandOperationOptions } from './command';
8
+ import { type CommandOperationOptions, ModernizedCommandOperation } from './command';
11
9
  import { Aspect, defineAspects } from './operation';
12
10
 
13
11
  /** @public */
@@ -28,7 +26,8 @@ export interface ListCollectionsOptions
28
26
  }
29
27
 
30
28
  /** @internal */
31
- export class ListCollectionsOperation extends CommandOperation<CursorResponse> {
29
+ export class ListCollectionsOperation extends ModernizedCommandOperation<CursorResponse> {
30
+ override SERVER_COMMAND_RESPONSE_TYPE = CursorResponse;
32
31
  /**
33
32
  * @remarks WriteConcern can still be present on the options because
34
33
  * we inherit options from the client/db/collection. The
@@ -56,28 +55,15 @@ export class ListCollectionsOperation extends CommandOperation<CursorResponse> {
56
55
  if (typeof this.options.batchSize === 'number') {
57
56
  this.batchSize = this.options.batchSize;
58
57
  }
58
+
59
+ this.SERVER_COMMAND_RESPONSE_TYPE = this.explain ? ExplainedCursorResponse : CursorResponse;
59
60
  }
60
61
 
61
62
  override get commandName() {
62
63
  return 'listCollections' as const;
63
64
  }
64
65
 
65
- override async execute(
66
- server: Server,
67
- session: ClientSession | undefined,
68
- timeoutContext: TimeoutContext
69
- ): Promise<CursorResponse> {
70
- return await super.executeCommand(
71
- server,
72
- session,
73
- this.generateCommand(maxWireVersion(server)),
74
- timeoutContext,
75
- CursorResponse
76
- );
77
- }
78
-
79
- /* This is here for the purpose of unit testing the final command that gets sent. */
80
- generateCommand(wireVersion: number): Document {
66
+ override buildCommandDocument(connection: Connection): Document {
81
67
  const command: Document = {
82
68
  listCollections: 1,
83
69
  filter: this.filter,
@@ -88,12 +74,18 @@ export class ListCollectionsOperation extends CommandOperation<CursorResponse> {
88
74
 
89
75
  // we check for undefined specifically here to allow falsy values
90
76
  // eslint-disable-next-line no-restricted-syntax
91
- if (wireVersion >= 9 && this.options.comment !== undefined) {
77
+ if (maxWireVersion(connection) >= 9 && this.options.comment !== undefined) {
92
78
  command.comment = this.options.comment;
93
79
  }
94
80
 
95
81
  return command;
96
82
  }
83
+
84
+ override handleOk(
85
+ response: InstanceType<typeof this.SERVER_COMMAND_RESPONSE_TYPE>
86
+ ): CursorResponse {
87
+ return response;
88
+ }
97
89
  }
98
90
 
99
91
  /** @public */
@@ -1,7 +1,9 @@
1
+ import { type Connection, type MongoError } from '..';
1
2
  import { type BSONSerializeOptions, type Document, resolveBSONOptions } from '../bson';
3
+ import { type MongoDBResponse } from '../cmap/wire_protocol/responses';
2
4
  import { type Abortable } from '../mongo_types';
3
5
  import { ReadPreference, type ReadPreferenceLike } from '../read_preference';
4
- import type { Server } from '../sdam/server';
6
+ import type { Server, ServerCommandOptions } from '../sdam/server';
5
7
  import type { ClientSession } from '../sessions';
6
8
  import { type TimeoutContext } from '../timeout';
7
9
  import type { MongoDBNamespace } from '../utils';
@@ -31,7 +33,6 @@ export interface OperationOptions extends BSONSerializeOptions {
31
33
 
32
34
  /** @internal Hints to `executeOperation` that this operation should not unpin on an ended transaction */
33
35
  bypassPinningCheck?: boolean;
34
- omitReadPreference?: boolean;
35
36
 
36
37
  /** @internal Hint to `executeOperation` to omit maxTimeMS */
37
38
  omitMaxTimeMS?: boolean;
@@ -55,7 +56,6 @@ export abstract class AbstractOperation<TResult = any> {
55
56
  readPreference: ReadPreference;
56
57
  server!: Server;
57
58
  bypassPinningCheck: boolean;
58
- trySecondaryWrite: boolean;
59
59
 
60
60
  // BSON serialization options
61
61
  bsonOptions?: BSONSerializeOptions;
@@ -81,7 +81,6 @@ export abstract class AbstractOperation<TResult = any> {
81
81
 
82
82
  this.options = options;
83
83
  this.bypassPinningCheck = !!options.bypassPinningCheck;
84
- this.trySecondaryWrite = false;
85
84
  }
86
85
 
87
86
  /** Must match the first key of the command object sent to the server.
@@ -108,6 +107,10 @@ export abstract class AbstractOperation<TResult = any> {
108
107
  return this._session;
109
108
  }
110
109
 
110
+ set session(session: ClientSession) {
111
+ this._session = session;
112
+ }
113
+
111
114
  clearSession() {
112
115
  this._session = undefined;
113
116
  }
@@ -125,6 +128,59 @@ export abstract class AbstractOperation<TResult = any> {
125
128
  }
126
129
  }
127
130
 
131
+ /** @internal */
132
+ export abstract class ModernizedOperation<TResult> extends AbstractOperation<TResult> {
133
+ abstract SERVER_COMMAND_RESPONSE_TYPE: typeof MongoDBResponse;
134
+
135
+ /** this will never be used - but we must implement it to satisfy AbstractOperation's interface */
136
+ override execute(
137
+ _server: Server,
138
+ _session: ClientSession | undefined,
139
+ _timeoutContext: TimeoutContext
140
+ ): Promise<TResult> {
141
+ throw new Error('cannot execute!!');
142
+ }
143
+
144
+ /**
145
+ * Build a raw command document.
146
+ */
147
+ abstract buildCommand(connection: Connection, session?: ClientSession): Document;
148
+
149
+ /**
150
+ * Builds an instance of `ServerCommandOptions` to be used for operation execution.
151
+ */
152
+ abstract buildOptions(timeoutContext: TimeoutContext): ServerCommandOptions;
153
+
154
+ /**
155
+ * Given an instance of a MongoDBResponse, map the response to the correct result type. For
156
+ * example, a `CountOperation` might map the response as follows:
157
+ *
158
+ * ```typescript
159
+ * override handleOk(response: InstanceType<typeof this.SERVER_COMMAND_RESPONSE_TYPE>): TResult {
160
+ * return response.toObject(this.bsonOptions).n ?? 0;
161
+ * }
162
+ *
163
+ * // or, with type safety:
164
+ * override handleOk(response: InstanceType<typeof this.SERVER_COMMAND_RESPONSE_TYPE>): TResult {
165
+ * return response.getNumber('n') ?? 0;
166
+ * }
167
+ * ```
168
+ */
169
+ handleOk(response: InstanceType<typeof this.SERVER_COMMAND_RESPONSE_TYPE>): TResult {
170
+ return response.toObject(this.bsonOptions) as TResult;
171
+ }
172
+
173
+ /**
174
+ * Optional.
175
+ *
176
+ * If the operation performs error handling, such as wrapping, renaming the error, or squashing errors
177
+ * this method can be overridden.
178
+ */
179
+ handleError(error: MongoError): TResult | never {
180
+ throw error;
181
+ }
182
+ }
183
+
128
184
  export function defineAspects(
129
185
  operation: { aspects?: Set<symbol> },
130
186
  aspects: symbol | symbol[] | Set<symbol>
@@ -1,13 +1,17 @@
1
+ import { type Connection, type MongoError } from '../..';
1
2
  import type { Document } from '../../bson';
3
+ import { MongoDBResponse } from '../../cmap/wire_protocol/responses';
2
4
  import type { Collection } from '../../collection';
3
5
  import { MONGODB_ERROR_CODES, MongoServerError } from '../../error';
4
- import type { Server } from '../../sdam/server';
6
+ import type { ServerCommandOptions } from '../../sdam/server';
5
7
  import type { ClientSession } from '../../sessions';
6
8
  import { type TimeoutContext } from '../../timeout';
7
- import { AbstractOperation } from '../operation';
9
+ import { ModernizedOperation } from '../operation';
8
10
 
9
11
  /** @internal */
10
- export class DropSearchIndexOperation extends AbstractOperation<void> {
12
+ export class DropSearchIndexOperation extends ModernizedOperation<void> {
13
+ override SERVER_COMMAND_RESPONSE_TYPE = MongoDBResponse;
14
+
11
15
  private readonly collection: Collection;
12
16
  private readonly name: string;
13
17
 
@@ -15,17 +19,14 @@ export class DropSearchIndexOperation extends AbstractOperation<void> {
15
19
  super();
16
20
  this.collection = collection;
17
21
  this.name = name;
22
+ this.ns = collection.fullNamespace;
18
23
  }
19
24
 
20
25
  override get commandName() {
21
26
  return 'dropSearchIndex' as const;
22
27
  }
23
28
 
24
- override async execute(
25
- server: Server,
26
- session: ClientSession | undefined,
27
- timeoutContext: TimeoutContext
28
- ): Promise<void> {
29
+ override buildCommand(_connection: Connection, _session?: ClientSession): Document {
29
30
  const namespace = this.collection.fullNamespace;
30
31
 
31
32
  const command: Document = {
@@ -36,14 +37,22 @@ export class DropSearchIndexOperation extends AbstractOperation<void> {
36
37
  command.name = this.name;
37
38
  }
38
39
 
39
- try {
40
- await server.command(namespace, command, { session, timeoutContext });
41
- } catch (error) {
42
- const isNamespaceNotFoundError =
43
- error instanceof MongoServerError && error.code === MONGODB_ERROR_CODES.NamespaceNotFound;
44
- if (!isNamespaceNotFoundError) {
45
- throw error;
46
- }
40
+ return command;
41
+ }
42
+
43
+ override handleOk(_response: MongoDBResponse): void {
44
+ // do nothing
45
+ }
46
+
47
+ override buildOptions(timeoutContext: TimeoutContext): ServerCommandOptions {
48
+ return { session: this.session, timeoutContext };
49
+ }
50
+
51
+ override handleError(error: MongoError): void {
52
+ const isNamespaceNotFoundError =
53
+ error instanceof MongoServerError && error.code === MONGODB_ERROR_CODES.NamespaceNotFound;
54
+ if (!isNamespaceNotFoundError) {
55
+ throw error;
47
56
  }
48
57
  }
49
58
  }
@@ -37,7 +37,9 @@ import {
37
37
  } from '../error';
38
38
  import type { ServerApi } from '../mongo_client';
39
39
  import { type Abortable, TypedEventEmitter } from '../mongo_types';
40
+ import { AggregateOperation } from '../operations/aggregate';
40
41
  import type { GetMoreOptions } from '../operations/get_more';
42
+ import { type ModernizedOperation } from '../operations/operation';
41
43
  import type { ClientSession } from '../sessions';
42
44
  import { type TimeoutContext } from '../timeout';
43
45
  import { isTransactionCommand } from '../transactions';
@@ -67,6 +69,7 @@ import type {
67
69
  } from './events';
68
70
  import { Monitor, type MonitorOptions } from './monitor';
69
71
  import { compareTopologyVersion, ServerDescription } from './server_description';
72
+ import { MIN_SECONDARY_WRITE_WIRE_VERSION } from './server_selection';
70
73
  import type { Topology } from './topology';
71
74
 
72
75
  const stateTransition = makeStateMachine({
@@ -110,6 +113,7 @@ export type ServerEvents = {
110
113
  /** @internal */
111
114
  export type ServerCommandOptions = Omit<CommandOptions, 'timeoutContext' | 'socketTimeoutMS'> & {
112
115
  timeoutContext: TimeoutContext;
116
+ returnFieldSelector?: Document | null;
113
117
  } & Abortable;
114
118
 
115
119
  /** @internal */
@@ -277,6 +281,100 @@ export class Server extends TypedEventEmitter<ServerEvents> {
277
281
  }
278
282
  }
279
283
 
284
+ public async modernCommand<TResult>(
285
+ operation: ModernizedOperation<TResult>,
286
+ timeoutContext: TimeoutContext
287
+ ): Promise<InstanceType<typeof operation.SERVER_COMMAND_RESPONSE_TYPE>> {
288
+ if (this.s.state === STATE_CLOSING || this.s.state === STATE_CLOSED) {
289
+ throw new MongoServerClosedError();
290
+ }
291
+ const session = operation.session;
292
+
293
+ let conn = session?.pinnedConnection;
294
+
295
+ this.incrementOperationCount();
296
+ if (conn == null) {
297
+ try {
298
+ conn = await this.pool.checkOut({ timeoutContext });
299
+ } catch (checkoutError) {
300
+ this.decrementOperationCount();
301
+ if (!(checkoutError instanceof PoolClearedError)) this.handleError(checkoutError);
302
+ throw checkoutError;
303
+ }
304
+ }
305
+
306
+ const cmd = operation.buildCommand(conn, session);
307
+ const options = operation.buildOptions(timeoutContext);
308
+ const ns = operation.ns;
309
+
310
+ if (this.loadBalanced && isPinnableCommand(cmd, session) && !session?.pinnedConnection) {
311
+ session?.pin(conn);
312
+ }
313
+
314
+ options.directConnection = this.topology.s.options.directConnection;
315
+
316
+ const omitReadPreference =
317
+ operation instanceof AggregateOperation &&
318
+ operation.hasWriteStage &&
319
+ maxWireVersion(conn) < MIN_SECONDARY_WRITE_WIRE_VERSION;
320
+ if (omitReadPreference) {
321
+ delete options.readPreference;
322
+ }
323
+
324
+ if (this.description.iscryptd) {
325
+ options.omitMaxTimeMS = true;
326
+ }
327
+
328
+ let reauthPromise: Promise<void> | null = null;
329
+
330
+ try {
331
+ try {
332
+ const res = await conn.command(ns, cmd, options, operation.SERVER_COMMAND_RESPONSE_TYPE);
333
+ throwIfWriteConcernError(res);
334
+ return res;
335
+ } catch (commandError) {
336
+ throw this.decorateCommandError(conn, cmd, options, commandError);
337
+ }
338
+ } catch (operationError) {
339
+ if (
340
+ operationError instanceof MongoError &&
341
+ operationError.code === MONGODB_ERROR_CODES.Reauthenticate
342
+ ) {
343
+ reauthPromise = this.pool.reauthenticate(conn);
344
+ reauthPromise.then(undefined, error => {
345
+ reauthPromise = null;
346
+ squashError(error);
347
+ });
348
+
349
+ await abortable(reauthPromise, options);
350
+ reauthPromise = null; // only reachable if reauth succeeds
351
+
352
+ try {
353
+ const res = await conn.command(ns, cmd, options, operation.SERVER_COMMAND_RESPONSE_TYPE);
354
+ throwIfWriteConcernError(res);
355
+ return res;
356
+ } catch (commandError) {
357
+ throw this.decorateCommandError(conn, cmd, options, commandError);
358
+ }
359
+ } else {
360
+ throw operationError;
361
+ }
362
+ } finally {
363
+ this.decrementOperationCount();
364
+ if (session?.pinnedConnection !== conn) {
365
+ if (reauthPromise != null) {
366
+ // The reauth promise only exists if it hasn't thrown.
367
+ const checkBackIn = () => {
368
+ this.pool.checkIn(conn);
369
+ };
370
+ void reauthPromise.then(checkBackIn, checkBackIn);
371
+ } else {
372
+ this.pool.checkIn(conn);
373
+ }
374
+ }
375
+ }
376
+ }
377
+
280
378
  public async command<T extends MongoDBResponseConstructor>(
281
379
  ns: MongoDBNamespace,
282
380
  command: Document,
@@ -306,14 +404,6 @@ export class Server extends TypedEventEmitter<ServerEvents> {
306
404
 
307
405
  options.directConnection = this.topology.s.options.directConnection;
308
406
 
309
- // There are cases where we need to flag the read preference not to get sent in
310
- // the command, such as pre-5.0 servers attempting to perform an aggregate write
311
- // with a non-primary read preference. In this case the effective read preference
312
- // (primary) is not the same as the provided and must be removed completely.
313
- if (options.omitReadPreference) {
314
- delete options.readPreference;
315
- }
316
-
317
407
  if (this.description.iscryptd) {
318
408
  options.omitMaxTimeMS = true;
319
409
  }
@@ -46,7 +46,6 @@ import {
46
46
  makeStateMachine,
47
47
  noop,
48
48
  now,
49
- ns,
50
49
  promiseWithResolvers,
51
50
  shuffle
52
51
  } from '../utils';
@@ -459,7 +458,7 @@ export class Topology extends TypedEventEmitter<TopologyEvents> {
459
458
  waitQueueTimeoutMS: this.client.s.options.waitQueueTimeoutMS
460
459
  });
461
460
  const selectServerOptions = {
462
- operationName: 'ping',
461
+ operationName: 'handshake',
463
462
  ...options,
464
463
  timeoutContext
465
464
  };
@@ -469,9 +468,11 @@ export class Topology extends TypedEventEmitter<TopologyEvents> {
469
468
  readPreferenceServerSelector(readPreference),
470
469
  selectServerOptions
471
470
  );
471
+
472
472
  const skipPingOnConnect = this.s.options.__skipPingOnConnect === true;
473
473
  if (!skipPingOnConnect && this.s.credentials) {
474
- await server.command(ns('admin.$cmd'), { ping: 1 }, { timeoutContext });
474
+ const connection = await server.pool.checkOut({ timeoutContext: timeoutContext });
475
+ server.pool.checkIn(connection);
475
476
  stateTransition(this, STATE_CONNECTED);
476
477
  this.emit(Topology.OPEN, this);
477
478
  this.emit(Topology.CONNECT, this);