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.
- package/lib/cmap/connection_pool.js +3 -2
- package/lib/core/connection/connect.js +15 -4
- package/lib/core/connection/connection.js +1 -0
- package/lib/core/error.js +46 -46
- package/lib/core/sdam/monitor.js +10 -2
- package/lib/core/sdam/server_description.js +4 -0
- package/lib/core/topologies/replset_state.js +5 -3
- package/lib/core/topologies/shared.js +4 -1
- package/lib/core/uri_parser.js +9 -0
- package/lib/error.js +21 -20
- package/lib/error_codes.js +36 -0
- package/lib/gridfs-stream/upload.js +8 -9
- package/lib/operations/db_ops.js +10 -7
- package/lib/operations/estimated_document_count.js +2 -1
- package/lib/topologies/native_topology.js +2 -0
- package/lib/url_parser.js +8 -0
- package/package.json +1 -1
|
@@ -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
|
|
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
|
|
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 >
|
|
280
|
-
keepAliveInitialDelay = Math.round(
|
|
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(
|
|
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
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
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
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
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
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
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
|
-
|
|
283
|
-
|
|
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
|
-
|
|
288
|
-
|
|
290
|
+
MONGODB_ERROR_CODES.InterruptedAtShutdown,
|
|
291
|
+
MONGODB_ERROR_CODES.ShutdownInProgress
|
|
289
292
|
]);
|
|
290
293
|
|
|
291
294
|
function isRecoveringError(err) {
|
|
292
|
-
if (err.code
|
|
293
|
-
|
|
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
|
|
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
|
|
301
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
332
|
-
return true;
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
return false;
|
|
335
|
+
return isRecoveringError(error) || isNotMasterError(error);
|
|
336
336
|
}
|
|
337
337
|
|
|
338
338
|
module.exports = {
|
package/lib/core/sdam/monitor.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
10
|
+
|
|
11
|
+
const MMAPv1_RETRY_WRITES_ERROR_CODE = MONGODB_ERROR_CODES.IllegalOperation;
|
|
9
12
|
|
|
10
13
|
/**
|
|
11
14
|
* Emit event if it exists
|
package/lib/core/uri_parser.js
CHANGED
|
@@ -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
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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 ===
|
|
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
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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 ===
|
|
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 ===
|
|
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) {
|
package/lib/operations/db_ops.js
CHANGED
|
@@ -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 ===
|
|
79
|
-
err.code ===
|
|
80
|
-
err.code ===
|
|
81
|
-
err.code ===
|
|
82
|
-
err.code ===
|
|
83
|
-
err.code ===
|
|
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 !==
|
|
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 !==
|
|
34
|
+
if (err && err.code !== MONGODB_ERROR_CODES.NamespaceNotFound) {
|
|
34
35
|
callback(err);
|
|
35
36
|
return;
|
|
36
37
|
}
|
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;
|