mongodb 3.7.0 → 3.7.1

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.
@@ -158,12 +158,13 @@ class ConnectionPool extends EventEmitter {
158
158
  waitQueueTimeoutMS:
159
159
  typeof options.waitQueueTimeoutMS === 'number' ? options.waitQueueTimeoutMS : 0,
160
160
  autoEncrypter: options.autoEncrypter,
161
- metadata: options.metadata
161
+ metadata: options.metadata,
162
+ useUnifiedTopology: options.useUnifiedTopology
162
163
  });
163
164
 
164
165
  if (options.minSize > options.maxSize) {
165
166
  throw new TypeError(
166
- 'Connection pool minimum size must not be greater than maxiumum pool size'
167
+ 'Connection pool minimum size must not be greater than maximum pool size'
167
168
  );
168
169
  }
169
170
 
@@ -95,6 +95,8 @@ function performInitialHandshake(conn, options, _callback) {
95
95
  handshakeOptions.socketTimeout = options.connectTimeoutMS || options.connectionTimeout;
96
96
  }
97
97
 
98
+ handshakeDoc.helloOk = !!options.useUnifiedTopology;
99
+
98
100
  const start = new Date().getTime();
99
101
  conn.command('admin.$cmd', handshakeDoc, handshakeOptions, (err, result) => {
100
102
  if (err) {
@@ -113,6 +115,10 @@ function performInitialHandshake(conn, options, _callback) {
113
115
  response.ismaster = response.isWritablePrimary;
114
116
  }
115
117
 
118
+ if (options.useUnifiedTopology && response.helloOk) {
119
+ conn.helloOk = true;
120
+ }
121
+
116
122
  const supportedServerErr = checkSupportedServer(response, options);
117
123
  if (supportedServerErr) {
118
124
  callback(supportedServerErr);
@@ -272,12 +278,17 @@ function makeConnection(family, options, cancellationToken, _callback) {
272
278
  : typeof options.connectTimeoutMS === 'number'
273
279
  ? options.connectTimeoutMS
274
280
  : 30000;
275
- const socketTimeout = typeof options.socketTimeout === 'number' ? options.socketTimeout : 0;
281
+ const socketTimeoutMS =
282
+ typeof options.socketTimeoutMS === 'number'
283
+ ? options.socketTimeoutMS
284
+ : typeof options.socketTimeout === 'number'
285
+ ? options.socketTimeout
286
+ : 0;
276
287
  const rejectUnauthorized =
277
288
  typeof options.rejectUnauthorized === 'boolean' ? options.rejectUnauthorized : true;
278
289
 
279
- if (keepAliveInitialDelay > socketTimeout) {
280
- keepAliveInitialDelay = Math.round(socketTimeout / 2);
290
+ if (keepAliveInitialDelay > socketTimeoutMS) {
291
+ keepAliveInitialDelay = Math.round(socketTimeoutMS / 2);
281
292
  }
282
293
 
283
294
  let socket;
@@ -330,7 +341,7 @@ function makeConnection(family, options, cancellationToken, _callback) {
330
341
  return callback(socket.authorizationError);
331
342
  }
332
343
 
333
- socket.setTimeout(socketTimeout);
344
+ socket.setTimeout(socketTimeoutMS);
334
345
  callback(null, socket);
335
346
  }
336
347
 
@@ -91,6 +91,7 @@ class Connection extends EventEmitter {
91
91
  this.bson = options.bson;
92
92
  this.tag = options.tag;
93
93
  this.maxBsonMessageSize = options.maxBsonMessageSize || DEFAULT_MAX_BSON_MESSAGE_SIZE;
94
+ this.helloOk = undefined;
94
95
 
95
96
  this.port = options.port || 27017;
96
97
  this.host = options.host || 'localhost';
package/lib/core/error.js CHANGED
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
2
 
3
+ const MONGODB_ERROR_CODES = require('../error_codes').MONGODB_ERROR_CODES;
4
+
3
5
  const kErrorLabels = Symbol('errorLabels');
4
6
 
5
7
  /**
@@ -216,32 +218,32 @@ class MongoWriteConcernError extends MongoError {
216
218
 
217
219
  // see: https://github.com/mongodb/specifications/blob/master/source/retryable-writes/retryable-writes.rst#terms
218
220
  const RETRYABLE_ERROR_CODES = new Set([
219
- 6, // HostUnreachable
220
- 7, // HostNotFound
221
- 89, // NetworkTimeout
222
- 91, // ShutdownInProgress
223
- 189, // PrimarySteppedDown
224
- 9001, // SocketException
225
- 10107, // NotMaster
226
- 11600, // InterruptedAtShutdown
227
- 11602, // InterruptedDueToReplStateChange
228
- 13435, // NotMasterNoSlaveOk
229
- 13436 // NotMasterOrSecondary
221
+ MONGODB_ERROR_CODES.HostUnreachable,
222
+ MONGODB_ERROR_CODES.HostNotFound,
223
+ MONGODB_ERROR_CODES.NetworkTimeout,
224
+ MONGODB_ERROR_CODES.ShutdownInProgress,
225
+ MONGODB_ERROR_CODES.PrimarySteppedDown,
226
+ MONGODB_ERROR_CODES.SocketException,
227
+ MONGODB_ERROR_CODES.NotMaster,
228
+ MONGODB_ERROR_CODES.InterruptedAtShutdown,
229
+ MONGODB_ERROR_CODES.InterruptedDueToReplStateChange,
230
+ MONGODB_ERROR_CODES.NotMasterNoSlaveOk,
231
+ MONGODB_ERROR_CODES.NotMasterOrSecondary
230
232
  ]);
231
233
 
232
234
  const RETRYABLE_WRITE_ERROR_CODES = new Set([
233
- 11600, // InterruptedAtShutdown
234
- 11602, // InterruptedDueToReplStateChange
235
- 10107, // NotMaster
236
- 13435, // NotMasterNoSlaveOk
237
- 13436, // NotMasterOrSecondary
238
- 189, // PrimarySteppedDown
239
- 91, // ShutdownInProgress
240
- 7, // HostNotFound
241
- 6, // HostUnreachable
242
- 89, // NetworkTimeout
243
- 9001, // SocketException
244
- 262 // ExceededTimeLimit
235
+ MONGODB_ERROR_CODES.InterruptedAtShutdown,
236
+ MONGODB_ERROR_CODES.InterruptedDueToReplStateChange,
237
+ MONGODB_ERROR_CODES.NotMaster,
238
+ MONGODB_ERROR_CODES.NotMasterNoSlaveOk,
239
+ MONGODB_ERROR_CODES.NotMasterOrSecondary,
240
+ MONGODB_ERROR_CODES.PrimarySteppedDown,
241
+ MONGODB_ERROR_CODES.ShutdownInProgress,
242
+ MONGODB_ERROR_CODES.HostNotFound,
243
+ MONGODB_ERROR_CODES.HostUnreachable,
244
+ MONGODB_ERROR_CODES.NetworkTimeout,
245
+ MONGODB_ERROR_CODES.SocketException,
246
+ MONGODB_ERROR_CODES.ExceededTimeLimit
245
247
  ]);
246
248
 
247
249
  function isRetryableWriteError(error) {
@@ -271,41 +273,44 @@ function isRetryableError(error) {
271
273
  }
272
274
 
273
275
  const SDAM_RECOVERING_CODES = new Set([
274
- 91, // ShutdownInProgress
275
- 189, // PrimarySteppedDown
276
- 11600, // InterruptedAtShutdown
277
- 11602, // InterruptedDueToReplStateChange
278
- 13436 // NotMasterOrSecondary
276
+ MONGODB_ERROR_CODES.ShutdownInProgress,
277
+ MONGODB_ERROR_CODES.PrimarySteppedDown,
278
+ MONGODB_ERROR_CODES.InterruptedAtShutdown,
279
+ MONGODB_ERROR_CODES.InterruptedDueToReplStateChange,
280
+ MONGODB_ERROR_CODES.NotMasterOrSecondary
279
281
  ]);
280
282
 
281
283
  const SDAM_NOTMASTER_CODES = new Set([
282
- 10107, // NotMaster
283
- 13435 // NotMasterNoSlaveOk
284
+ MONGODB_ERROR_CODES.NotMaster,
285
+ MONGODB_ERROR_CODES.NotMasterNoSlaveOk,
286
+ MONGODB_ERROR_CODES.LegacyNotPrimary
284
287
  ]);
285
288
 
286
289
  const SDAM_NODE_SHUTTING_DOWN_ERROR_CODES = new Set([
287
- 11600, // InterruptedAtShutdown
288
- 91 // ShutdownInProgress
290
+ MONGODB_ERROR_CODES.InterruptedAtShutdown,
291
+ MONGODB_ERROR_CODES.ShutdownInProgress
289
292
  ]);
290
293
 
291
294
  function isRecoveringError(err) {
292
- if (err.code && SDAM_RECOVERING_CODES.has(err.code)) {
293
- return true;
295
+ if (typeof err.code === 'number') {
296
+ // If any error code exists, we ignore the error.message
297
+ return SDAM_RECOVERING_CODES.has(err.code);
294
298
  }
295
299
 
296
- return err.message.match(/not master or secondary/) || err.message.match(/node is recovering/);
300
+ return /not master or secondary/.test(err.message) || /node is recovering/.test(err.message);
297
301
  }
298
302
 
299
303
  function isNotMasterError(err) {
300
- if (err.code && SDAM_NOTMASTER_CODES.has(err.code)) {
301
- return true;
304
+ if (typeof err.code === 'number') {
305
+ // If any error code exists, we ignore the error.message
306
+ return SDAM_NOTMASTER_CODES.has(err.code);
302
307
  }
303
308
 
304
309
  if (isRecoveringError(err)) {
305
310
  return false;
306
311
  }
307
312
 
308
- return err.message.match(/not master/);
313
+ return /not master/.test(err.message);
309
314
  }
310
315
 
311
316
  function isNodeShuttingDownError(err) {
@@ -316,10 +321,9 @@ function isNodeShuttingDownError(err) {
316
321
  * Determines whether SDAM can recover from a given error. If it cannot
317
322
  * then the pool will be cleared, and server state will completely reset
318
323
  * locally.
319
- *
320
- * @ignore
321
324
  * @see https://github.com/mongodb/specifications/blob/master/source/server-discovery-and-monitoring/server-discovery-and-monitoring.rst#not-master-and-node-is-recovering
322
- * @param {MongoError|Error} error
325
+ * @param {MongoError} error
326
+ * @returns {boolean}
323
327
  */
324
328
  function isSDAMUnrecoverableError(error) {
325
329
  // NOTE: null check is here for a strictly pre-CMAP world, a timeout or
@@ -328,11 +332,7 @@ function isSDAMUnrecoverableError(error) {
328
332
  return true;
329
333
  }
330
334
 
331
- if (isRecoveringError(error) || isNotMasterError(error)) {
332
- return true;
333
- }
334
-
335
- return false;
335
+ return isRecoveringError(error) || isNotMasterError(error);
336
336
  }
337
337
 
338
338
  module.exports = {
@@ -65,7 +65,8 @@ class Monitor extends EventEmitter {
65
65
  heartbeatFrequencyMS:
66
66
  typeof options.heartbeatFrequencyMS === 'number' ? options.heartbeatFrequencyMS : 10000,
67
67
  minHeartbeatFrequencyMS:
68
- typeof options.minHeartbeatFrequencyMS === 'number' ? options.minHeartbeatFrequencyMS : 500
68
+ typeof options.minHeartbeatFrequencyMS === 'number' ? options.minHeartbeatFrequencyMS : 500,
69
+ useUnifiedTopology: options.useUnifiedTopology
69
70
  });
70
71
 
71
72
  // TODO: refactor this to pull it directly from the pool, requires new ConnectionPool integration
@@ -205,8 +206,15 @@ function checkServer(monitor, callback) {
205
206
  const topologyVersion = monitor[kServer].description.topologyVersion;
206
207
  const isAwaitable = topologyVersion != null;
207
208
  const serverApi = monitor[kConnection].serverApi;
209
+ const helloOk = monitor[kConnection].helloOk;
210
+
211
+ const cmd = {
212
+ [serverApi || helloOk ? 'hello' : 'ismaster']: true
213
+ };
214
+
215
+ // written this way omit helloOk from the command if its false-y (do not want -> helloOk: null)
216
+ if (helloOk) cmd.helloOk = helloOk;
208
217
 
209
- const cmd = { [serverApi ? 'hello' : 'ismaster']: true };
210
218
  const options = { socketTimeout: connectTimeoutMS };
211
219
 
212
220
  if (isAwaitable) {
@@ -70,6 +70,10 @@ class ServerDescription {
70
70
  ismaster
71
71
  );
72
72
 
73
+ if (ismaster.isWritablePrimary != null) {
74
+ ismaster.ismaster = ismaster.isWritablePrimary;
75
+ }
76
+
73
77
  this.address = address;
74
78
  this.error = options.error;
75
79
  this.roundTripTime = options.roundTripTime || -1;
@@ -34,7 +34,7 @@ var ReplSetState = function(options) {
34
34
  // Add event listener
35
35
  EventEmitter.call(this);
36
36
  // Topology state
37
- this.topologyType = TopologyType.ReplicaSetNoPrimary;
37
+ this.topologyType = options.setName ? TopologyType.ReplicaSetNoPrimary : TopologyType.Unknown;
38
38
  this.setName = options.setName;
39
39
 
40
40
  // Server set
@@ -218,7 +218,8 @@ const isArbiter = ismaster => ismaster.arbiterOnly && ismaster.setName;
218
218
  ReplSetState.prototype.update = function(server) {
219
219
  var self = this;
220
220
  // Get the current ismaster
221
- var ismaster = server.lastIsMaster();
221
+ const ismaster = server.lastIsMaster();
222
+ if (ismaster && ismaster.isWritablePrimary) ismaster.ismaster = ismaster.isWritablePrimary;
222
223
 
223
224
  // Get the server name and lowerCase it
224
225
  var serverName = server.name.toLowerCase();
@@ -358,7 +359,8 @@ ReplSetState.prototype.update = function(server) {
358
359
  // Standalone server, destroy and return
359
360
  //
360
361
  if (ismaster && ismaster.ismaster && !ismaster.setName) {
361
- this.topologyType = this.primary ? TopologyType.ReplicaSetWithPrimary : TopologyType.Unknown;
362
+ // We should not mark the topology as Unknown because of one standalone
363
+ // we should just remove this server from the set
362
364
  this.remove(server, { force: true });
363
365
  return false;
364
366
  }
@@ -1,11 +1,14 @@
1
1
  'use strict';
2
+
3
+ const MONGODB_ERROR_CODES = require('../../error_codes').MONGODB_ERROR_CODES;
2
4
  const ReadPreference = require('./read_preference');
3
5
  const TopologyType = require('../sdam/common').TopologyType;
4
6
  const MongoError = require('../error').MongoError;
5
7
  const isRetryableWriteError = require('../error').isRetryableWriteError;
6
8
  const maxWireVersion = require('../utils').maxWireVersion;
7
9
  const MongoNetworkError = require('../error').MongoNetworkError;
8
- const MMAPv1_RETRY_WRITES_ERROR_CODE = 20;
10
+
11
+ const MMAPv1_RETRY_WRITES_ERROR_CODE = MONGODB_ERROR_CODES.IllegalOperation;
9
12
 
10
13
  /**
11
14
  * Emit event if it exists
@@ -106,6 +106,11 @@ function parseSrvConnectionString(uri, options, callback) {
106
106
  }
107
107
 
108
108
  record = qs.parse(record[0].join(''));
109
+
110
+ if (Object.keys(record).some(k => k.toLowerCase() === 'loadbalanced')) {
111
+ return callback(new MongoParseError('Load balancer mode requires driver version 4+'));
112
+ }
113
+
109
114
  if (Object.keys(record).some(key => key !== 'authSource' && key !== 'replicaSet')) {
110
115
  return callback(
111
116
  new MongoParseError('Text record must only set `authSource` or `replicaSet`')
@@ -598,6 +603,10 @@ function parseConnectionString(uri, options, callback) {
598
603
 
599
604
  parsedOptions = Object.assign({}, parsedOptions, options);
600
605
 
606
+ if (Object.keys(parsedOptions).some(k => k.toLowerCase() === 'loadbalanced')) {
607
+ return callback(new MongoParseError('Load balancer mode requires driver version 4+'));
608
+ }
609
+
601
610
  if (protocol === PROTOCOL_MONGODB_SRV) {
602
611
  return parseSrvConnectionString(uri, parsedOptions, callback);
603
612
  }
package/lib/error.js CHANGED
@@ -1,27 +1,28 @@
1
1
  'use strict';
2
2
 
3
3
  const MongoNetworkError = require('./core').MongoNetworkError;
4
+ const MONGODB_ERROR_CODES = require('./error_codes').MONGODB_ERROR_CODES;
4
5
 
5
6
  // From spec@https://github.com/mongodb/specifications/blob/f93d78191f3db2898a59013a7ed5650352ef6da8/source/change-streams/change-streams.rst#resumable-error
6
7
  const GET_MORE_RESUMABLE_CODES = new Set([
7
- 6, // HostUnreachable
8
- 7, // HostNotFound
9
- 89, // NetworkTimeout
10
- 91, // ShutdownInProgress
11
- 189, // PrimarySteppedDown
12
- 262, // ExceededTimeLimit
13
- 9001, // SocketException
14
- 10107, // NotMaster
15
- 11600, // InterruptedAtShutdown
16
- 11602, // InterruptedDueToReplStateChange
17
- 13435, // NotMasterNoSlaveOk
18
- 13436, // NotMasterOrSecondary
19
- 63, // StaleShardVersion
20
- 150, // StaleEpoch
21
- 13388, // StaleConfig
22
- 234, // RetryChangeStream
23
- 133, // FailedToSatisfyReadPreference
24
- 43 // CursorNotFound
8
+ MONGODB_ERROR_CODES.HostUnreachable,
9
+ MONGODB_ERROR_CODES.HostNotFound,
10
+ MONGODB_ERROR_CODES.NetworkTimeout,
11
+ MONGODB_ERROR_CODES.ShutdownInProgress,
12
+ MONGODB_ERROR_CODES.PrimarySteppedDown,
13
+ MONGODB_ERROR_CODES.ExceededTimeLimit,
14
+ MONGODB_ERROR_CODES.SocketException,
15
+ MONGODB_ERROR_CODES.NotMaster,
16
+ MONGODB_ERROR_CODES.InterruptedAtShutdown,
17
+ MONGODB_ERROR_CODES.InterruptedDueToReplStateChange,
18
+ MONGODB_ERROR_CODES.NotMasterNoSlaveOk,
19
+ MONGODB_ERROR_CODES.NotMasterOrSecondary,
20
+ MONGODB_ERROR_CODES.StaleShardVersion,
21
+ MONGODB_ERROR_CODES.StaleEpoch,
22
+ MONGODB_ERROR_CODES.StaleConfig,
23
+ MONGODB_ERROR_CODES.RetryChangeStream,
24
+ MONGODB_ERROR_CODES.FailedToSatisfyReadPreference,
25
+ MONGODB_ERROR_CODES.CursorNotFound
25
26
  ]);
26
27
 
27
28
  function isResumableError(error, wireVersion) {
@@ -31,7 +32,7 @@ function isResumableError(error, wireVersion) {
31
32
 
32
33
  if (wireVersion >= 9) {
33
34
  // DRIVERS-1308: For 4.4 drivers running against 4.4 servers, drivers will add a special case to treat the CursorNotFound error code as resumable
34
- if (error.code === 43) {
35
+ if (error.code === MONGODB_ERROR_CODES.CursorNotFound) {
35
36
  return true;
36
37
  }
37
38
  return error.hasErrorLabel('ResumableChangeStreamError');
@@ -40,4 +41,4 @@ function isResumableError(error, wireVersion) {
40
41
  return GET_MORE_RESUMABLE_CODES.has(error.code);
41
42
  }
42
43
 
43
- module.exports = { GET_MORE_RESUMABLE_CODES, isResumableError };
44
+ module.exports = { GET_MORE_RESUMABLE_CODES, isResumableError, MONGODB_ERROR_CODES };
@@ -0,0 +1,36 @@
1
+ 'use strict';
2
+
3
+ const MONGODB_ERROR_CODES = Object.freeze({
4
+ HostUnreachable: 6,
5
+ HostNotFound: 7,
6
+ NetworkTimeout: 89,
7
+ ShutdownInProgress: 91,
8
+ PrimarySteppedDown: 189,
9
+ ExceededTimeLimit: 262,
10
+ SocketException: 9001,
11
+ NotMaster: 10107,
12
+ InterruptedAtShutdown: 11600,
13
+ InterruptedDueToReplStateChange: 11602,
14
+ NotMasterNoSlaveOk: 13435,
15
+ NotMasterOrSecondary: 13436,
16
+ StaleShardVersion: 63,
17
+ StaleEpoch: 150,
18
+ StaleConfig: 13388,
19
+ RetryChangeStream: 234,
20
+ FailedToSatisfyReadPreference: 133,
21
+ CursorNotFound: 43,
22
+ LegacyNotPrimary: 10058,
23
+ WriteConcernFailed: 64,
24
+ NamespaceNotFound: 26,
25
+ IllegalOperation: 20,
26
+ MaxTimeMSExpired: 50,
27
+ UnknownReplWriteConcern: 79,
28
+ UnsatisfiableWriteConcern: 100,
29
+ DuplicateKey: 11000,
30
+ CannotCreateIndex: 67,
31
+ IndexOptionsConflict: 85,
32
+ IndexKeySpecsConflict: 86,
33
+ InvalidIndexSpecificationOption: 197
34
+ });
35
+
36
+ module.exports = Object.freeze({ MONGODB_ERROR_CODES });
@@ -1,14 +1,13 @@
1
1
  'use strict';
2
2
 
3
- var core = require('../core');
4
- var crypto = require('crypto');
5
- var stream = require('stream');
6
- var util = require('util');
7
- var Buffer = require('safe-buffer').Buffer;
3
+ const MONGODB_ERROR_CODES = require('../error_codes').MONGODB_ERROR_CODES;
4
+ const core = require('../core');
5
+ const crypto = require('crypto');
6
+ const stream = require('stream');
7
+ const util = require('util');
8
+ const Buffer = require('safe-buffer').Buffer;
8
9
  const deprecateOptions = require('../utils').deprecateOptions;
9
10
 
10
- const ERROR_NAMESPACE_NOT_FOUND = 26;
11
-
12
11
  /**
13
12
  * A writable stream that enables you to write buffers to GridFS.
14
13
  *
@@ -216,7 +215,7 @@ function checkChunksIndex(_this, callback) {
216
215
  _this.chunks.listIndexes().toArray(function(error, indexes) {
217
216
  if (error) {
218
217
  // Collection doesn't exist so create index
219
- if (error.code === ERROR_NAMESPACE_NOT_FOUND) {
218
+ if (error.code === MONGODB_ERROR_CODES.NamespaceNotFound) {
220
219
  var index = { files_id: 1, n: 1 };
221
220
  _this.chunks.createIndex(index, { background: false, unique: true }, function(error) {
222
221
  if (error) {
@@ -315,7 +314,7 @@ function checkIndexes(_this, callback) {
315
314
  _this.files.listIndexes().toArray(function(error, indexes) {
316
315
  if (error) {
317
316
  // Collection doesn't exist so create index
318
- if (error.code === ERROR_NAMESPACE_NOT_FOUND) {
317
+ if (error.code === MONGODB_ERROR_CODES.NamespaceNotFound) {
319
318
  var index = { filename: 1, uploadDate: 1 };
320
319
  _this.files.createIndex(index, { background: false }, function(error) {
321
320
  if (error) {
@@ -1,5 +1,6 @@
1
1
  'use strict';
2
2
 
3
+ const MONGODB_ERROR_CODES = require('../error_codes').MONGODB_ERROR_CODES;
3
4
  const applyWriteConcern = require('../utils').applyWriteConcern;
4
5
  const Code = require('../core').BSON.Code;
5
6
  const debugOptions = require('../utils').debugOptions;
@@ -75,12 +76,12 @@ function createIndex(db, name, fieldOrSpec, options, callback) {
75
76
  * 197 = 'InvalidIndexSpecificationOption' (`_id` with `background: true`)
76
77
  */
77
78
  if (
78
- err.code === 67 ||
79
- err.code === 11000 ||
80
- err.code === 85 ||
81
- err.code === 86 ||
82
- err.code === 11600 ||
83
- err.code === 197
79
+ err.code === MONGODB_ERROR_CODES.CannotCreateIndex ||
80
+ err.code === MONGODB_ERROR_CODES.DuplicateKey ||
81
+ err.code === MONGODB_ERROR_CODES.IndexOptionsConflict ||
82
+ err.code === MONGODB_ERROR_CODES.IndexKeySpecsConflict ||
83
+ err.code === MONGODB_ERROR_CODES.InterruptedAtShutdown ||
84
+ err.code === MONGODB_ERROR_CODES.InvalidIndexSpecificationOption
84
85
  ) {
85
86
  return handleCallback(callback, err, result);
86
87
  }
@@ -147,7 +148,9 @@ function ensureIndex(db, name, fieldOrSpec, options, callback) {
147
148
 
148
149
  // Check if the index already exists
149
150
  indexInformation(db, name, finalOptions, (err, indexInformation) => {
150
- if (err != null && err.code !== 26) return handleCallback(callback, err, null);
151
+ if (err != null && err.code !== MONGODB_ERROR_CODES.NamespaceNotFound) {
152
+ return handleCallback(callback, err, null);
153
+ }
151
154
  // If the index does not exist, create it
152
155
  if (indexInformation == null || !indexInformation[index_name]) {
153
156
  createIndex(db, name, fieldOrSpec, options, callback);
@@ -1,5 +1,6 @@
1
1
  'use strict';
2
2
 
3
+ const MONGODB_ERROR_CODES = require('../error_codes').MONGODB_ERROR_CODES;
3
4
  const Aspect = require('./operation').Aspect;
4
5
  const defineAspects = require('./operation').defineAspects;
5
6
  const CommandOperationV2 = require('./command_v2');
@@ -30,7 +31,7 @@ class EstimatedDocumentCountOperation extends CommandOperationV2 {
30
31
  }
31
32
 
32
33
  super.executeCommand(server, cmd, (err, response) => {
33
- if (err && err.code !== 26) {
34
+ if (err && err.code !== MONGODB_ERROR_CODES.NamespaceNotFound) {
34
35
  callback(err);
35
36
  return;
36
37
  }
@@ -46,6 +46,8 @@ class NativeTopology extends Topology {
46
46
 
47
47
  clonedOptions.serverApi = options.serverApi;
48
48
 
49
+ clonedOptions.useUnifiedTopology = options.useUnifiedTopology;
50
+
49
51
  super(servers, clonedOptions);
50
52
  }
51
53
 
package/lib/url_parser.js CHANGED
@@ -101,6 +101,9 @@ module.exports = function(url, options, callback) {
101
101
  record = record[0].join('');
102
102
  const parsedRecord = qs.parse(record);
103
103
  const items = Object.keys(parsedRecord);
104
+ if (Object.keys(items).some(k => k.toLowerCase() === 'loadbalanced')) {
105
+ return callback(new MongoParseError('Load balancer mode requires driver version 4+'));
106
+ }
104
107
  if (items.some(item => item !== 'authSource' && item !== 'replicaSet')) {
105
108
  return callback(
106
109
  new MongoParseError('Text record must only set `authSource` or `replicaSet`')
@@ -378,6 +381,11 @@ function parseConnectionString(url, options) {
378
381
  object.dbName = dbName || 'admin';
379
382
  // Split up all the options
380
383
  urlOptions = (query_string_part || '').split(/[&;]/);
384
+
385
+ if (urlOptions.some(k => k.toLowerCase() === 'loadbalanced')) {
386
+ throw new MongoParseError('Load balancer mode requires driver version 4+');
387
+ }
388
+
381
389
  // Ugh, we have to figure out which options go to which constructor manually.
382
390
  urlOptions.forEach(function(opt) {
383
391
  if (!opt) return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mongodb",
3
- "version": "3.7.0",
3
+ "version": "3.7.1",
4
4
  "description": "The official MongoDB driver for Node.js",
5
5
  "main": "index.js",
6
6
  "files": [