mongodb 6.12.0-dev.20241211.sha.2f9ad4d4 → 6.12.0-dev.20241212.sha.f6d7868f

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.
package/src/error.ts CHANGED
@@ -10,9 +10,6 @@ import type { TopologyDescription } from './sdam/topology_description';
10
10
  /** @public */
11
11
  export type AnyError = MongoError | Error;
12
12
 
13
- /** @internal */
14
- const kErrorLabels = Symbol('errorLabels');
15
-
16
13
  /**
17
14
  * @internal
18
15
  * The legacy error message from the server that indicates the node is not a writable primary
@@ -129,7 +126,11 @@ function isAggregateError(e: unknown): e is Error & { errors: Error[] } {
129
126
  */
130
127
  export class MongoError extends Error {
131
128
  /** @internal */
132
- [kErrorLabels]: Set<string>;
129
+ private readonly errorLabelSet: Set<string> = new Set();
130
+ public get errorLabels(): string[] {
131
+ return Array.from(this.errorLabelSet);
132
+ }
133
+
133
134
  /**
134
135
  * This is a number in MongoServerError and a string in MongoDriverError
135
136
  * @privateRemarks
@@ -153,7 +154,6 @@ export class MongoError extends Error {
153
154
  **/
154
155
  constructor(message: string, options?: { cause?: Error }) {
155
156
  super(message, options);
156
- this[kErrorLabels] = new Set();
157
157
  }
158
158
 
159
159
  /** @internal */
@@ -188,15 +188,11 @@ export class MongoError extends Error {
188
188
  * @returns returns true if the error has the provided error label
189
189
  */
190
190
  hasErrorLabel(label: string): boolean {
191
- return this[kErrorLabels].has(label);
191
+ return this.errorLabelSet.has(label);
192
192
  }
193
193
 
194
194
  addErrorLabel(label: string): void {
195
- this[kErrorLabels].add(label);
196
- }
197
-
198
- get errorLabels(): string[] {
199
- return Array.from(this[kErrorLabels]);
195
+ this.errorLabelSet.add(label);
200
196
  }
201
197
  }
202
198
 
@@ -228,8 +224,9 @@ export class MongoServerError extends MongoError {
228
224
  **/
229
225
  constructor(message: ErrorDescription) {
230
226
  super(message.message || message.errmsg || message.$err || 'n/a');
227
+
231
228
  if (message.errorLabels) {
232
- this[kErrorLabels] = new Set(message.errorLabels);
229
+ for (const label of message.errorLabels) this.addErrorLabel(label);
233
230
  }
234
231
 
235
232
  this.errorResponse = message;
@@ -1028,12 +1025,6 @@ export class MongoTopologyClosedError extends MongoAPIError {
1028
1025
  }
1029
1026
  }
1030
1027
 
1031
- /** @internal */
1032
- const kBeforeHandshake = Symbol('beforeHandshake');
1033
- export function isNetworkErrorBeforeHandshake(err: MongoNetworkError): boolean {
1034
- return err[kBeforeHandshake] === true;
1035
- }
1036
-
1037
1028
  /** @public */
1038
1029
  export interface MongoNetworkErrorOptions {
1039
1030
  /** Indicates the timeout happened before a connection handshake completed */
@@ -1048,7 +1039,7 @@ export interface MongoNetworkErrorOptions {
1048
1039
  */
1049
1040
  export class MongoNetworkError extends MongoError {
1050
1041
  /** @internal */
1051
- [kBeforeHandshake]?: boolean;
1042
+ public readonly beforeHandshake: boolean;
1052
1043
 
1053
1044
  /**
1054
1045
  * **Do not use this constructor!**
@@ -1063,10 +1054,7 @@ export class MongoNetworkError extends MongoError {
1063
1054
  **/
1064
1055
  constructor(message: string, options?: MongoNetworkErrorOptions) {
1065
1056
  super(message, { cause: options?.cause });
1066
-
1067
- if (options && typeof options.beforeHandshake === 'boolean') {
1068
- this[kBeforeHandshake] = options.beforeHandshake;
1069
- }
1057
+ this.beforeHandshake = !!options?.beforeHandshake;
1070
1058
  }
1071
1059
 
1072
1060
  override get name(): string {
@@ -333,9 +333,6 @@ export type MongoClientEvents = Pick<TopologyEvents, (typeof MONGO_CLIENT_EVENTS
333
333
  open(mongoClient: MongoClient): void;
334
334
  };
335
335
 
336
- /** @internal */
337
- const kOptions = Symbol('options');
338
-
339
336
  /**
340
337
  * The **MongoClient** class is a class that allows for making Connections to MongoDB.
341
338
  * @public
@@ -367,20 +364,22 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> implements
367
364
 
368
365
  /**
369
366
  * The consolidate, parsed, transformed and merged options.
370
- * @internal
371
367
  */
372
- [kOptions]: MongoOptions;
368
+ public readonly options: Readonly<
369
+ Omit<MongoOptions, 'monitorCommands' | 'ca' | 'crl' | 'key' | 'cert'>
370
+ > &
371
+ Pick<MongoOptions, 'monitorCommands' | 'ca' | 'crl' | 'key' | 'cert'>;
373
372
 
374
373
  constructor(url: string, options?: MongoClientOptions) {
375
374
  super();
376
375
 
377
- this[kOptions] = parseOptions(url, this, options);
376
+ this.options = parseOptions(url, this, options);
378
377
 
379
- const shouldSetLogger = Object.values(
380
- this[kOptions].mongoLoggerOptions.componentSeverities
381
- ).some(value => value !== SeverityLevel.OFF);
378
+ const shouldSetLogger = Object.values(this.options.mongoLoggerOptions.componentSeverities).some(
379
+ value => value !== SeverityLevel.OFF
380
+ );
382
381
  this.mongoLogger = shouldSetLogger
383
- ? new MongoLogger(this[kOptions].mongoLoggerOptions)
382
+ ? new MongoLogger(this.options.mongoLoggerOptions)
384
383
  : undefined;
385
384
 
386
385
  // eslint-disable-next-line @typescript-eslint/no-this-alias
@@ -389,7 +388,7 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> implements
389
388
  // The internal state
390
389
  this.s = {
391
390
  url,
392
- bsonOptions: resolveBSONOptions(this[kOptions]),
391
+ bsonOptions: resolveBSONOptions(this.options),
393
392
  namespace: ns('admin'),
394
393
  hasBeenClosed: false,
395
394
  sessionPool: new ServerSessionPool(this),
@@ -397,16 +396,16 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> implements
397
396
  authProviders: new MongoClientAuthProviders(),
398
397
 
399
398
  get options() {
400
- return client[kOptions];
399
+ return client.options;
401
400
  },
402
401
  get readConcern() {
403
- return client[kOptions].readConcern;
402
+ return client.options.readConcern;
404
403
  },
405
404
  get writeConcern() {
406
- return client[kOptions].writeConcern;
405
+ return client.options.writeConcern;
407
406
  },
408
407
  get readPreference() {
409
- return client[kOptions].readPreference;
408
+ return client.options.readPreference;
410
409
  },
411
410
  get isMongoClient(): true {
412
411
  return true;
@@ -428,15 +427,15 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> implements
428
427
 
429
428
  /** @internal */
430
429
  private checkForNonGenuineHosts() {
431
- const documentDBHostnames = this[kOptions].hosts.filter((hostAddress: HostAddress) =>
430
+ const documentDBHostnames = this.options.hosts.filter((hostAddress: HostAddress) =>
432
431
  isHostMatch(DOCUMENT_DB_CHECK, hostAddress.host)
433
432
  );
434
- const srvHostIsDocumentDB = isHostMatch(DOCUMENT_DB_CHECK, this[kOptions].srvHost);
433
+ const srvHostIsDocumentDB = isHostMatch(DOCUMENT_DB_CHECK, this.options.srvHost);
435
434
 
436
- const cosmosDBHostnames = this[kOptions].hosts.filter((hostAddress: HostAddress) =>
435
+ const cosmosDBHostnames = this.options.hosts.filter((hostAddress: HostAddress) =>
437
436
  isHostMatch(COSMOS_DB_CHECK, hostAddress.host)
438
437
  );
439
- const srvHostIsCosmosDB = isHostMatch(COSMOS_DB_CHECK, this[kOptions].srvHost);
438
+ const srvHostIsCosmosDB = isHostMatch(COSMOS_DB_CHECK, this.options.srvHost);
440
439
 
441
440
  if (documentDBHostnames.length !== 0 || srvHostIsDocumentDB) {
442
441
  this.mongoLogger?.info('client', DOCUMENT_DB_MSG);
@@ -445,28 +444,23 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> implements
445
444
  }
446
445
  }
447
446
 
448
- /** @see MongoOptions */
449
- get options(): Readonly<MongoOptions> {
450
- return Object.freeze({ ...this[kOptions] });
451
- }
452
-
453
447
  get serverApi(): Readonly<ServerApi | undefined> {
454
- return this[kOptions].serverApi && Object.freeze({ ...this[kOptions].serverApi });
448
+ return this.options.serverApi && Object.freeze({ ...this.options.serverApi });
455
449
  }
456
450
  /**
457
451
  * Intended for APM use only
458
452
  * @internal
459
453
  */
460
454
  get monitorCommands(): boolean {
461
- return this[kOptions].monitorCommands;
455
+ return this.options.monitorCommands;
462
456
  }
463
457
  set monitorCommands(value: boolean) {
464
- this[kOptions].monitorCommands = value;
458
+ this.options.monitorCommands = value;
465
459
  }
466
460
 
467
461
  /** @internal */
468
462
  get autoEncrypter(): AutoEncrypter | undefined {
469
- return this[kOptions].autoEncrypter;
463
+ return this.options.autoEncrypter;
470
464
  }
471
465
 
472
466
  get readConcern(): ReadConcern | undefined {
@@ -551,7 +545,7 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> implements
551
545
  return this;
552
546
  }
553
547
 
554
- const options = this[kOptions];
548
+ const options = this.options;
555
549
 
556
550
  if (options.tls) {
557
551
  if (typeof options.tlsCAFile === 'string') {
@@ -685,7 +679,7 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> implements
685
679
 
686
680
  topology.close();
687
681
 
688
- const { encrypter } = this[kOptions];
682
+ const { encrypter } = this.options;
689
683
  if (encrypter) {
690
684
  await encrypter.close(this, force);
691
685
  }
@@ -706,7 +700,7 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> implements
706
700
  }
707
701
 
708
702
  // Copy the options and add out internal override of the not shared flag
709
- const finalOptions = Object.assign({}, this[kOptions], options);
703
+ const finalOptions = Object.assign({}, this.options, options);
710
704
 
711
705
  // Return the db object
712
706
  const db = new Db(this, dbName, finalOptions);
@@ -748,7 +742,7 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> implements
748
742
  this,
749
743
  this.s.sessionPool,
750
744
  { explicit: true, ...options },
751
- this[kOptions]
745
+ this.options
752
746
  );
753
747
  this.s.activeSessions.add(session);
754
748
  session.once('ended', () => {
@@ -42,9 +42,6 @@ export interface OperationOptions extends BSONSerializeOptions {
42
42
  timeoutMS?: number;
43
43
  }
44
44
 
45
- /** @internal */
46
- const kSession = Symbol('session');
47
-
48
45
  /**
49
46
  * This class acts as a parent class for any operation and is responsible for setting this.options,
50
47
  * as well as setting and getting a session.
@@ -67,7 +64,7 @@ export abstract class AbstractOperation<TResult = any> {
67
64
  /** Specifies the time an operation will run until it throws a timeout error. */
68
65
  timeoutMS?: number;
69
66
 
70
- [kSession]: ClientSession | undefined;
67
+ private _session: ClientSession | undefined;
71
68
 
72
69
  static aspects?: Set<symbol>;
73
70
 
@@ -79,7 +76,7 @@ export abstract class AbstractOperation<TResult = any> {
79
76
  // Pull the BSON serialize options from the already-resolved options
80
77
  this.bsonOptions = resolveBSONOptions(options);
81
78
 
82
- this[kSession] = options.session != null ? options.session : undefined;
79
+ this._session = options.session != null ? options.session : undefined;
83
80
 
84
81
  this.options = options;
85
82
  this.bypassPinningCheck = !!options.bypassPinningCheck;
@@ -105,12 +102,13 @@ export abstract class AbstractOperation<TResult = any> {
105
102
  return ctor.aspects.has(aspect);
106
103
  }
107
104
 
105
+ // Make sure the session is not writable from outside this class.
108
106
  get session(): ClientSession | undefined {
109
- return this[kSession];
107
+ return this._session;
110
108
  }
111
109
 
112
110
  clearSession() {
113
- this[kSession] = undefined;
111
+ this._session = undefined;
114
112
  }
115
113
 
116
114
  resetBatch(): boolean {
@@ -25,13 +25,6 @@ import {
25
25
  import { Server } from './server';
26
26
  import type { TopologyVersion } from './server_description';
27
27
 
28
- /** @internal */
29
- const kServer = Symbol('server');
30
- /** @internal */
31
- const kMonitorId = Symbol('monitorId');
32
- /** @internal */
33
- const kCancellationToken = Symbol('cancellationToken');
34
-
35
28
  const STATE_IDLE = 'idle';
36
29
  const STATE_MONITORING = 'monitoring';
37
30
  const stateTransition = makeStateMachine({
@@ -96,11 +89,11 @@ export class Monitor extends TypedEventEmitter<MonitorEvents> {
96
89
  >;
97
90
  connectOptions: ConnectionOptions;
98
91
  isRunningInFaasEnv: boolean;
99
- [kServer]: Server;
92
+ server: Server;
100
93
  connection: Connection | null;
101
- [kCancellationToken]: CancellationToken;
94
+ cancellationToken: CancellationToken;
102
95
  /** @internal */
103
- [kMonitorId]?: MonitorInterval;
96
+ monitorId?: MonitorInterval;
104
97
  rttPinger?: RTTPinger;
105
98
  /** @internal */
106
99
  override component = MongoLoggableComponent.TOPOLOGY;
@@ -110,11 +103,11 @@ export class Monitor extends TypedEventEmitter<MonitorEvents> {
110
103
  constructor(server: Server, options: MonitorOptions) {
111
104
  super();
112
105
 
113
- this[kServer] = server;
106
+ this.server = server;
114
107
  this.connection = null;
115
- this[kCancellationToken] = new CancellationToken();
116
- this[kCancellationToken].setMaxListeners(Infinity);
117
- this[kMonitorId] = undefined;
108
+ this.cancellationToken = new CancellationToken();
109
+ this.cancellationToken.setMaxListeners(Infinity);
110
+ this.monitorId = undefined;
118
111
  this.s = {
119
112
  state: STATE_CLOSED
120
113
  };
@@ -126,10 +119,10 @@ export class Monitor extends TypedEventEmitter<MonitorEvents> {
126
119
  serverMonitoringMode: options.serverMonitoringMode
127
120
  });
128
121
  this.isRunningInFaasEnv = getFAASEnv() != null;
129
- this.mongoLogger = this[kServer].topology.client?.mongoLogger;
122
+ this.mongoLogger = this.server.topology.client?.mongoLogger;
130
123
  this.rttSampler = new RTTSampler(10);
131
124
 
132
- const cancellationToken = this[kCancellationToken];
125
+ const cancellationToken = this.cancellationToken;
133
126
  // TODO: refactor this to pull it directly from the pool, requires new ConnectionPool integration
134
127
  const connectOptions = {
135
128
  id: '<monitor>' as const,
@@ -162,7 +155,7 @@ export class Monitor extends TypedEventEmitter<MonitorEvents> {
162
155
  // start
163
156
  const heartbeatFrequencyMS = this.options.heartbeatFrequencyMS;
164
157
  const minHeartbeatFrequencyMS = this.options.minHeartbeatFrequencyMS;
165
- this[kMonitorId] = new MonitorInterval(monitorServer(this), {
158
+ this.monitorId = new MonitorInterval(monitorServer(this), {
166
159
  heartbeatFrequencyMS: heartbeatFrequencyMS,
167
160
  minHeartbeatFrequencyMS: minHeartbeatFrequencyMS,
168
161
  immediate: true
@@ -174,11 +167,11 @@ export class Monitor extends TypedEventEmitter<MonitorEvents> {
174
167
  return;
175
168
  }
176
169
 
177
- this[kMonitorId]?.wake();
170
+ this.monitorId?.wake();
178
171
  }
179
172
 
180
173
  reset(): void {
181
- const topologyVersion = this[kServer].description.topologyVersion;
174
+ const topologyVersion = this.server.description.topologyVersion;
182
175
  if (isInCloseState(this) || topologyVersion == null) {
183
176
  return;
184
177
  }
@@ -192,7 +185,7 @@ export class Monitor extends TypedEventEmitter<MonitorEvents> {
192
185
  // restart monitoring
193
186
  const heartbeatFrequencyMS = this.options.heartbeatFrequencyMS;
194
187
  const minHeartbeatFrequencyMS = this.options.minHeartbeatFrequencyMS;
195
- this[kMonitorId] = new MonitorInterval(monitorServer(this), {
188
+ this.monitorId = new MonitorInterval(monitorServer(this), {
196
189
  heartbeatFrequencyMS: heartbeatFrequencyMS,
197
190
  minHeartbeatFrequencyMS: minHeartbeatFrequencyMS
198
191
  });
@@ -233,13 +226,13 @@ export class Monitor extends TypedEventEmitter<MonitorEvents> {
233
226
  }
234
227
 
235
228
  function resetMonitorState(monitor: Monitor) {
236
- monitor[kMonitorId]?.stop();
237
- monitor[kMonitorId] = undefined;
229
+ monitor.monitorId?.stop();
230
+ monitor.monitorId = undefined;
238
231
 
239
232
  monitor.rttPinger?.close();
240
233
  monitor.rttPinger = undefined;
241
234
 
242
- monitor[kCancellationToken].emit('cancel');
235
+ monitor.cancellationToken.emit('cancel');
243
236
 
244
237
  monitor.connection?.destroy();
245
238
  monitor.connection = null;
@@ -266,11 +259,11 @@ function useStreamingProtocol(monitor: Monitor, topologyVersion: TopologyVersion
266
259
  function checkServer(monitor: Monitor, callback: Callback<Document | null>) {
267
260
  let start: number;
268
261
  let awaited: boolean;
269
- const topologyVersion = monitor[kServer].description.topologyVersion;
262
+ const topologyVersion = monitor.server.description.topologyVersion;
270
263
  const isAwaitable = useStreamingProtocol(monitor, topologyVersion);
271
264
  monitor.emitAndLogHeartbeat(
272
265
  Server.SERVER_HEARTBEAT_STARTED,
273
- monitor[kServer].topology.s.id,
266
+ monitor.server.topology.s.id,
274
267
  undefined,
275
268
  new ServerHeartbeatStartedEvent(monitor.address, isAwaitable)
276
269
  );
@@ -280,7 +273,7 @@ function checkServer(monitor: Monitor, callback: Callback<Document | null>) {
280
273
  monitor.connection = null;
281
274
  monitor.emitAndLogHeartbeat(
282
275
  Server.SERVER_HEARTBEAT_FAILED,
283
- monitor[kServer].topology.s.id,
276
+ monitor.server.topology.s.id,
284
277
  undefined,
285
278
  new ServerHeartbeatFailedEvent(monitor.address, calculateDurationInMs(start), err, awaited)
286
279
  );
@@ -315,7 +308,7 @@ function checkServer(monitor: Monitor, callback: Callback<Document | null>) {
315
308
 
316
309
  monitor.emitAndLogHeartbeat(
317
310
  Server.SERVER_HEARTBEAT_SUCCEEDED,
318
- monitor[kServer].topology.s.id,
311
+ monitor.server.topology.s.id,
319
312
  hello.connectionId,
320
313
  new ServerHeartbeatSucceededEvent(monitor.address, duration, hello, isAwaitable)
321
314
  );
@@ -325,7 +318,7 @@ function checkServer(monitor: Monitor, callback: Callback<Document | null>) {
325
318
  // event, otherwise the "check" is complete and return to the main monitor loop
326
319
  monitor.emitAndLogHeartbeat(
327
320
  Server.SERVER_HEARTBEAT_STARTED,
328
- monitor[kServer].topology.s.id,
321
+ monitor.server.topology.s.id,
329
322
  undefined,
330
323
  new ServerHeartbeatStartedEvent(monitor.address, true)
331
324
  );
@@ -378,7 +371,6 @@ function checkServer(monitor: Monitor, callback: Callback<Document | null>) {
378
371
  awaited = false;
379
372
  connection
380
373
  .command(ns('admin.$cmd'), cmd, options)
381
-
382
374
  .then(onHeartbeatSucceeded, onHeartbeatFailed);
383
375
 
384
376
  return;
@@ -409,7 +401,7 @@ function checkServer(monitor: Monitor, callback: Callback<Document | null>) {
409
401
  monitor.connection = connection;
410
402
  monitor.emitAndLogHeartbeat(
411
403
  Server.SERVER_HEARTBEAT_SUCCEEDED,
412
- monitor[kServer].topology.s.id,
404
+ monitor.server.topology.s.id,
413
405
  connection.hello?.connectionId,
414
406
  new ServerHeartbeatSucceededEvent(
415
407
  monitor.address,
@@ -447,7 +439,7 @@ function monitorServer(monitor: Monitor) {
447
439
  checkServer(monitor, (err, hello) => {
448
440
  if (err) {
449
441
  // otherwise an error occurred on initial discovery, also bail
450
- if (monitor[kServer].description.type === ServerType.Unknown) {
442
+ if (monitor.server.description.type === ServerType.Unknown) {
451
443
  return done();
452
444
  }
453
445
  }
@@ -456,7 +448,7 @@ function monitorServer(monitor: Monitor) {
456
448
  if (useStreamingProtocol(monitor, hello?.topologyVersion)) {
457
449
  setTimeout(() => {
458
450
  if (!isInCloseState(monitor)) {
459
- monitor[kMonitorId]?.wake();
451
+ monitor.monitorId?.wake();
460
452
  }
461
453
  }, 0);
462
454
  }
@@ -484,9 +476,9 @@ export interface RTTPingerOptions extends ConnectionOptions {
484
476
  export class RTTPinger {
485
477
  connection?: Connection;
486
478
  /** @internal */
487
- [kCancellationToken]: CancellationToken;
479
+ cancellationToken: CancellationToken;
488
480
  /** @internal */
489
- [kMonitorId]: NodeJS.Timeout;
481
+ monitorId: NodeJS.Timeout;
490
482
  /** @internal */
491
483
  monitor: Monitor;
492
484
  closed: boolean;
@@ -495,13 +487,13 @@ export class RTTPinger {
495
487
 
496
488
  constructor(monitor: Monitor) {
497
489
  this.connection = undefined;
498
- this[kCancellationToken] = monitor[kCancellationToken];
490
+ this.cancellationToken = monitor.cancellationToken;
499
491
  this.closed = false;
500
492
  this.monitor = monitor;
501
493
  this.latestRtt = monitor.latestRtt ?? undefined;
502
494
 
503
495
  const heartbeatFrequencyMS = monitor.options.heartbeatFrequencyMS;
504
- this[kMonitorId] = setTimeout(() => this.measureRoundTripTime(), heartbeatFrequencyMS);
496
+ this.monitorId = setTimeout(() => this.measureRoundTripTime(), heartbeatFrequencyMS);
505
497
  }
506
498
 
507
499
  get roundTripTime(): number {
@@ -514,7 +506,7 @@ export class RTTPinger {
514
506
 
515
507
  close(): void {
516
508
  this.closed = true;
517
- clearTimeout(this[kMonitorId]);
509
+ clearTimeout(this.monitorId);
518
510
 
519
511
  this.connection?.destroy();
520
512
  this.connection = undefined;
@@ -531,7 +523,7 @@ export class RTTPinger {
531
523
  }
532
524
 
533
525
  this.latestRtt = calculateDurationInMs(start);
534
- this[kMonitorId] = setTimeout(
526
+ this.monitorId = setTimeout(
535
527
  () => this.measureRoundTripTime(),
536
528
  this.monitor.options.heartbeatFrequencyMS
537
529
  );
@@ -22,7 +22,6 @@ import {
22
22
  } from '../constants';
23
23
  import {
24
24
  type AnyError,
25
- isNetworkErrorBeforeHandshake,
26
25
  isNodeShuttingDownError,
27
26
  isSDAMUnrecoverableError,
28
27
  MONGODB_ERROR_CODES,
@@ -381,7 +380,8 @@ export class Server extends TypedEventEmitter<ServerEvents> {
381
380
 
382
381
  const isNetworkNonTimeoutError =
383
382
  error instanceof MongoNetworkError && !(error instanceof MongoNetworkTimeoutError);
384
- const isNetworkTimeoutBeforeHandshakeError = isNetworkErrorBeforeHandshake(error);
383
+ const isNetworkTimeoutBeforeHandshakeError =
384
+ error instanceof MongoNetworkError && error.beforeHandshake;
385
385
  const isAuthHandshakeError = error.hasErrorLabel(MongoErrorLabel.HandshakeError);
386
386
  if (isNetworkNonTimeoutError || isNetworkTimeoutBeforeHandshakeError || isAuthHandshakeError) {
387
387
  // In load balanced mode we never mark the server as unknown and always
@@ -88,11 +88,6 @@ const stateTransition = makeStateMachine({
88
88
  [STATE_CLOSING]: [STATE_CLOSING, STATE_CLOSED]
89
89
  });
90
90
 
91
- /** @internal */
92
- const kCancelled = Symbol('cancelled');
93
- /** @internal */
94
- const kWaitQueue = Symbol('waitQueue');
95
-
96
91
  /** @internal */
97
92
  export type ServerSelectionCallback = Callback<Server>;
98
93
 
@@ -105,7 +100,7 @@ export interface ServerSelectionRequest {
105
100
  startTime: number;
106
101
  resolve: (server: Server) => void;
107
102
  reject: (error: MongoError) => void;
108
- [kCancelled]?: boolean;
103
+ cancelled: boolean;
109
104
  operationName: string;
110
105
  waitingLogged: boolean;
111
106
  previousServer?: ServerDescription;
@@ -208,7 +203,7 @@ export class Topology extends TypedEventEmitter<TopologyEvents> {
208
203
  /** @internal */
209
204
  s: TopologyPrivate;
210
205
  /** @internal */
211
- [kWaitQueue]: List<ServerSelectionRequest>;
206
+ waitQueue: List<ServerSelectionRequest>;
212
207
  /** @internal */
213
208
  hello?: Document;
214
209
  /** @internal */
@@ -293,7 +288,7 @@ export class Topology extends TypedEventEmitter<TopologyEvents> {
293
288
  serverDescriptions.set(hostAddress.toString(), new ServerDescription(hostAddress));
294
289
  }
295
290
 
296
- this[kWaitQueue] = new List();
291
+ this.waitQueue = new List();
297
292
  this.s = {
298
293
  // the id of this topology
299
294
  id: topologyId,
@@ -506,7 +501,7 @@ export class Topology extends TypedEventEmitter<TopologyEvents> {
506
501
 
507
502
  stateTransition(this, STATE_CLOSING);
508
503
 
509
- drainWaitQueue(this[kWaitQueue], new MongoTopologyClosedError());
504
+ drainWaitQueue(this.waitQueue, new MongoTopologyClosedError());
510
505
 
511
506
  if (this.s.srvPoller) {
512
507
  this.s.srvPoller.stop();
@@ -601,13 +596,14 @@ export class Topology extends TypedEventEmitter<TopologyEvents> {
601
596
  transaction,
602
597
  resolve,
603
598
  reject,
599
+ cancelled: false,
604
600
  startTime: now(),
605
601
  operationName: options.operationName,
606
602
  waitingLogged: false,
607
603
  previousServer: options.previousServer
608
604
  };
609
605
 
610
- this[kWaitQueue].push(waitQueueMember);
606
+ this.waitQueue.push(waitQueueMember);
611
607
  processWaitQueue(this);
612
608
 
613
609
  try {
@@ -620,7 +616,7 @@ export class Topology extends TypedEventEmitter<TopologyEvents> {
620
616
  } catch (error) {
621
617
  if (TimeoutError.is(error)) {
622
618
  // Timeout
623
- waitQueueMember[kCancelled] = true;
619
+ waitQueueMember.cancelled = true;
624
620
  const timeoutError = new MongoServerSelectionError(
625
621
  `Server selection timed out after ${timeout?.duration} ms`,
626
622
  this.description
@@ -721,7 +717,7 @@ export class Topology extends TypedEventEmitter<TopologyEvents> {
721
717
  updateServers(this, serverDescription);
722
718
 
723
719
  // attempt to resolve any outstanding server selection attempts
724
- if (this[kWaitQueue].length > 0) {
720
+ if (this.waitQueue.length > 0) {
725
721
  processWaitQueue(this);
726
722
  }
727
723
 
@@ -910,7 +906,7 @@ function drainWaitQueue(queue: List<ServerSelectionRequest>, drainError: MongoDr
910
906
  continue;
911
907
  }
912
908
 
913
- if (!waitQueueMember[kCancelled]) {
909
+ if (!waitQueueMember.cancelled) {
914
910
  if (
915
911
  waitQueueMember.mongoLogger?.willLog(
916
912
  MongoLoggableComponent.SERVER_SELECTION,
@@ -934,20 +930,20 @@ function drainWaitQueue(queue: List<ServerSelectionRequest>, drainError: MongoDr
934
930
 
935
931
  function processWaitQueue(topology: Topology) {
936
932
  if (topology.s.state === STATE_CLOSED) {
937
- drainWaitQueue(topology[kWaitQueue], new MongoTopologyClosedError());
933
+ drainWaitQueue(topology.waitQueue, new MongoTopologyClosedError());
938
934
  return;
939
935
  }
940
936
 
941
937
  const isSharded = topology.description.type === TopologyType.Sharded;
942
938
  const serverDescriptions = Array.from(topology.description.servers.values());
943
- const membersToProcess = topology[kWaitQueue].length;
939
+ const membersToProcess = topology.waitQueue.length;
944
940
  for (let i = 0; i < membersToProcess; ++i) {
945
- const waitQueueMember = topology[kWaitQueue].shift();
941
+ const waitQueueMember = topology.waitQueue.shift();
946
942
  if (!waitQueueMember) {
947
943
  continue;
948
944
  }
949
945
 
950
- if (waitQueueMember[kCancelled]) {
946
+ if (waitQueueMember.cancelled) {
951
947
  continue;
952
948
  }
953
949
 
@@ -1006,7 +1002,7 @@ function processWaitQueue(topology: Topology) {
1006
1002
  }
1007
1003
  waitQueueMember.waitingLogged = true;
1008
1004
  }
1009
- topology[kWaitQueue].push(waitQueueMember);
1005
+ topology.waitQueue.push(waitQueueMember);
1010
1006
  continue;
1011
1007
  } else if (selectedDescriptions.length === 1) {
1012
1008
  selectedServer = topology.s.servers.get(selectedDescriptions[0].address);
@@ -1069,7 +1065,7 @@ function processWaitQueue(topology: Topology) {
1069
1065
  waitQueueMember.resolve(selectedServer);
1070
1066
  }
1071
1067
 
1072
- if (topology[kWaitQueue].length > 0) {
1068
+ if (topology.waitQueue.length > 0) {
1073
1069
  // ensure all server monitors attempt monitoring soon
1074
1070
  for (const [, server] of topology.s.servers) {
1075
1071
  process.nextTick(function scheduleServerCheck() {