mongodb 3.3.1 → 3.3.4
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/HISTORY.md +82 -0
- package/lib/aggregation_cursor.js +1 -1
- package/lib/bulk/common.js +166 -73
- package/lib/bulk/ordered.js +1 -1
- package/lib/bulk/unordered.js +1 -0
- package/lib/change_stream.js +2 -3
- package/lib/collection.js +70 -15
- package/lib/command_cursor.js +1 -1
- package/lib/core/connection/connect.js +20 -5
- package/lib/core/connection/connection.js +7 -3
- package/lib/core/connection/msg.js +3 -2
- package/lib/core/connection/pool.js +192 -206
- package/lib/core/cursor.js +1 -1
- package/lib/core/error.js +6 -1
- package/lib/core/sdam/monitoring.js +8 -1
- package/lib/core/sdam/server.js +90 -34
- package/lib/core/sdam/server_description.js +29 -0
- package/lib/core/sdam/topology.js +200 -91
- package/lib/core/sdam/topology_description.js +5 -3
- package/lib/core/topologies/mongos.js +72 -24
- package/lib/core/topologies/replset.js +34 -15
- package/lib/core/topologies/replset_state.js +5 -5
- package/lib/core/topologies/server.js +13 -12
- package/lib/core/topologies/shared.js +11 -15
- package/lib/core/uri_parser.js +8 -2
- package/lib/core/utils.js +40 -2
- package/lib/cursor.js +1 -1
- package/lib/db.js +3 -3
- package/lib/gridfs-stream/download.js +12 -5
- package/lib/gridfs-stream/index.js +1 -1
- package/lib/mongo_client.js +3 -3
- package/lib/operations/close.js +6 -2
- package/lib/operations/common_functions.js +4 -0
- package/lib/operations/connect.js +16 -13
- package/lib/operations/execute_operation.js +28 -12
- package/lib/operations/replace_one.js +1 -1
- package/lib/topologies/mongos.js +1 -1
- package/lib/topologies/replset.js +1 -1
- package/lib/topologies/server.js +1 -1
- package/lib/topologies/topology_base.js +4 -5
- package/package.json +11 -5
|
@@ -30,14 +30,15 @@ var DISCONNECTED = 'disconnected';
|
|
|
30
30
|
var CONNECTING = 'connecting';
|
|
31
31
|
var CONNECTED = 'connected';
|
|
32
32
|
var UNREFERENCED = 'unreferenced';
|
|
33
|
+
var DESTROYING = 'destroying';
|
|
33
34
|
var DESTROYED = 'destroyed';
|
|
34
35
|
|
|
35
36
|
function stateTransition(self, newState) {
|
|
36
37
|
var legalTransitions = {
|
|
37
|
-
disconnected: [CONNECTING, DESTROYED, DISCONNECTED],
|
|
38
|
-
connecting: [CONNECTING, DESTROYED, CONNECTED, DISCONNECTED],
|
|
39
|
-
connected: [CONNECTED, DISCONNECTED, DESTROYED, UNREFERENCED],
|
|
40
|
-
unreferenced: [UNREFERENCED, DESTROYED],
|
|
38
|
+
disconnected: [CONNECTING, DESTROYING, DESTROYED, DISCONNECTED],
|
|
39
|
+
connecting: [CONNECTING, DESTROYING, DESTROYED, CONNECTED, DISCONNECTED],
|
|
40
|
+
connected: [CONNECTED, DISCONNECTED, DESTROYING, DESTROYED, UNREFERENCED],
|
|
41
|
+
unreferenced: [UNREFERENCED, DESTROYING, DESTROYED],
|
|
41
42
|
destroyed: [DESTROYED]
|
|
42
43
|
};
|
|
43
44
|
|
|
@@ -46,9 +47,9 @@ function stateTransition(self, newState) {
|
|
|
46
47
|
if (legalStates && legalStates.indexOf(newState) !== -1) {
|
|
47
48
|
self.state = newState;
|
|
48
49
|
} else {
|
|
49
|
-
self.logger.error(
|
|
50
|
+
self.s.logger.error(
|
|
50
51
|
f(
|
|
51
|
-
'
|
|
52
|
+
'Mongos with id [%s] failed attempted illegal state transition from [%s] to [%s] only following state allowed [%s]',
|
|
52
53
|
self.id,
|
|
53
54
|
self.state,
|
|
54
55
|
newState,
|
|
@@ -292,7 +293,10 @@ Mongos.prototype.auth = function(credentials, callback) {
|
|
|
292
293
|
|
|
293
294
|
function handleEvent(self) {
|
|
294
295
|
return function() {
|
|
295
|
-
if (self.state === DESTROYED)
|
|
296
|
+
if (self.state === DESTROYED || self.state === DESTROYING) {
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
|
|
296
300
|
// Move to list of disconnectedProxies
|
|
297
301
|
moveServerFrom(self.connectedProxies, self.disconnectedProxies, this);
|
|
298
302
|
// Emit the initial topology
|
|
@@ -366,7 +370,8 @@ function handleInitialConnectEvent(self, event) {
|
|
|
366
370
|
self.s.logger.warn(f(message, _this.name));
|
|
367
371
|
}
|
|
368
372
|
|
|
369
|
-
// This is not a mongos proxy, remove it completely
|
|
373
|
+
// This is not a mongos proxy, destroy and remove it completely
|
|
374
|
+
_this.destroy(true);
|
|
370
375
|
removeProxyFrom(self.connectingProxies, _this);
|
|
371
376
|
// Emit the left event
|
|
372
377
|
self.emit('left', 'server', _this);
|
|
@@ -445,10 +450,9 @@ function connectProxies(self, servers) {
|
|
|
445
450
|
server.connect(self.s.connectOptions);
|
|
446
451
|
}, timeoutInterval);
|
|
447
452
|
}
|
|
453
|
+
|
|
448
454
|
// Start all the servers
|
|
449
|
-
|
|
450
|
-
connect(servers.shift(), timeoutInterval++);
|
|
451
|
-
}
|
|
455
|
+
servers.forEach(server => connect(server, timeoutInterval++));
|
|
452
456
|
}
|
|
453
457
|
|
|
454
458
|
function pickProxy(self, session) {
|
|
@@ -541,14 +545,14 @@ function reconnectProxies(self, proxies, callback) {
|
|
|
541
545
|
count = count - 1;
|
|
542
546
|
|
|
543
547
|
// Destroyed
|
|
544
|
-
if (self.state === DESTROYED || self.state === UNREFERENCED) {
|
|
548
|
+
if (self.state === DESTROYED || self.state === DESTROYING || self.state === UNREFERENCED) {
|
|
545
549
|
moveServerFrom(self.connectingProxies, self.disconnectedProxies, _self);
|
|
546
550
|
return this.destroy();
|
|
547
551
|
}
|
|
548
552
|
|
|
549
553
|
if (event === 'connect') {
|
|
550
554
|
// Destroyed
|
|
551
|
-
if (self.state === DESTROYED || self.state === UNREFERENCED) {
|
|
555
|
+
if (self.state === DESTROYED || self.state === DESTROYING || self.state === UNREFERENCED) {
|
|
552
556
|
moveServerFrom(self.connectingProxies, self.disconnectedProxies, _self);
|
|
553
557
|
return _self.destroy();
|
|
554
558
|
}
|
|
@@ -592,7 +596,7 @@ function reconnectProxies(self, proxies, callback) {
|
|
|
592
596
|
function execute(_server, i) {
|
|
593
597
|
setTimeout(function() {
|
|
594
598
|
// Destroyed
|
|
595
|
-
if (self.state === DESTROYED || self.state === UNREFERENCED) {
|
|
599
|
+
if (self.state === DESTROYED || self.state === DESTROYING || self.state === UNREFERENCED) {
|
|
596
600
|
return;
|
|
597
601
|
}
|
|
598
602
|
|
|
@@ -608,7 +612,7 @@ function reconnectProxies(self, proxies, callback) {
|
|
|
608
612
|
})
|
|
609
613
|
);
|
|
610
614
|
|
|
611
|
-
destroyServer(_server);
|
|
615
|
+
destroyServer(_server, { force: true });
|
|
612
616
|
removeProxyFrom(self.disconnectedProxies, _server);
|
|
613
617
|
|
|
614
618
|
// Relay the server description change
|
|
@@ -645,9 +649,17 @@ function reconnectProxies(self, proxies, callback) {
|
|
|
645
649
|
function topologyMonitor(self, options) {
|
|
646
650
|
options = options || {};
|
|
647
651
|
|
|
652
|
+
// no need to set up the monitor if we're already closed
|
|
653
|
+
if (self.state === DESTROYED || self.state === DESTROYING || self.state === UNREFERENCED) {
|
|
654
|
+
return;
|
|
655
|
+
}
|
|
656
|
+
|
|
648
657
|
// Set momitoring timeout
|
|
649
658
|
self.haTimeoutId = setTimeout(function() {
|
|
650
|
-
if (self.state === DESTROYED || self.state === UNREFERENCED)
|
|
659
|
+
if (self.state === DESTROYED || self.state === DESTROYING || self.state === UNREFERENCED) {
|
|
660
|
+
return;
|
|
661
|
+
}
|
|
662
|
+
|
|
651
663
|
// If we have a primary and a disconnect handler, execute
|
|
652
664
|
// buffered operations
|
|
653
665
|
if (self.isConnected() && self.s.disconnectHandler) {
|
|
@@ -678,7 +690,11 @@ function topologyMonitor(self, options) {
|
|
|
678
690
|
socketTimeout: self.s.options.connectionTimeout || 2000
|
|
679
691
|
},
|
|
680
692
|
function(err, r) {
|
|
681
|
-
if (
|
|
693
|
+
if (
|
|
694
|
+
self.state === DESTROYED ||
|
|
695
|
+
self.state === DESTROYING ||
|
|
696
|
+
self.state === UNREFERENCED
|
|
697
|
+
) {
|
|
682
698
|
// Move from connectingProxies
|
|
683
699
|
moveServerFrom(self.connectedProxies, self.disconnectedProxies, _server);
|
|
684
700
|
_server.destroy();
|
|
@@ -727,7 +743,9 @@ function topologyMonitor(self, options) {
|
|
|
727
743
|
|
|
728
744
|
// Attempt to connect to any unknown servers
|
|
729
745
|
return reconnectProxies(self, self.disconnectedProxies, function() {
|
|
730
|
-
if (self.state === DESTROYED || self.state === UNREFERENCED)
|
|
746
|
+
if (self.state === DESTROYED || self.state === DESTROYING || self.state === UNREFERENCED) {
|
|
747
|
+
return;
|
|
748
|
+
}
|
|
731
749
|
|
|
732
750
|
// Are we connected ? emit connect event
|
|
733
751
|
if (self.state === CONNECTING && options.firstConnect) {
|
|
@@ -751,11 +769,24 @@ function topologyMonitor(self, options) {
|
|
|
751
769
|
count = count - 1;
|
|
752
770
|
|
|
753
771
|
if (count === 0) {
|
|
754
|
-
if (
|
|
772
|
+
if (
|
|
773
|
+
self.state === DESTROYED ||
|
|
774
|
+
self.state === DESTROYING ||
|
|
775
|
+
self.state === UNREFERENCED
|
|
776
|
+
) {
|
|
777
|
+
return;
|
|
778
|
+
}
|
|
755
779
|
|
|
756
780
|
// Attempt to connect to any unknown servers
|
|
757
781
|
reconnectProxies(self, self.disconnectedProxies, function() {
|
|
758
|
-
if (
|
|
782
|
+
if (
|
|
783
|
+
self.state === DESTROYED ||
|
|
784
|
+
self.state === DESTROYING ||
|
|
785
|
+
self.state === UNREFERENCED
|
|
786
|
+
) {
|
|
787
|
+
return;
|
|
788
|
+
}
|
|
789
|
+
|
|
759
790
|
// Perform topology monitor
|
|
760
791
|
topologyMonitor(self);
|
|
761
792
|
});
|
|
@@ -796,6 +827,14 @@ Mongos.prototype.unref = function() {
|
|
|
796
827
|
* @method
|
|
797
828
|
*/
|
|
798
829
|
Mongos.prototype.destroy = function(options, callback) {
|
|
830
|
+
if (typeof options === 'function') {
|
|
831
|
+
callback = options;
|
|
832
|
+
options = {};
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
options = options || {};
|
|
836
|
+
|
|
837
|
+
stateTransition(this, DESTROYING);
|
|
799
838
|
if (this.haTimeoutId) {
|
|
800
839
|
clearTimeout(this.haTimeoutId);
|
|
801
840
|
}
|
|
@@ -929,7 +968,9 @@ Mongos.prototype.insert = function(ns, ops, options, callback) {
|
|
|
929
968
|
(callback = options), (options = {}), (options = options || {});
|
|
930
969
|
}
|
|
931
970
|
|
|
932
|
-
if (this.state === DESTROYED)
|
|
971
|
+
if (this.state === DESTROYED) {
|
|
972
|
+
return callback(new MongoError(f('topology was destroyed')));
|
|
973
|
+
}
|
|
933
974
|
|
|
934
975
|
// Not connected but we have a disconnecthandler
|
|
935
976
|
if (!this.isConnected() && this.s.disconnectHandler != null) {
|
|
@@ -963,7 +1004,9 @@ Mongos.prototype.update = function(ns, ops, options, callback) {
|
|
|
963
1004
|
(callback = options), (options = {}), (options = options || {});
|
|
964
1005
|
}
|
|
965
1006
|
|
|
966
|
-
if (this.state === DESTROYED)
|
|
1007
|
+
if (this.state === DESTROYED) {
|
|
1008
|
+
return callback(new MongoError(f('topology was destroyed')));
|
|
1009
|
+
}
|
|
967
1010
|
|
|
968
1011
|
// Not connected but we have a disconnecthandler
|
|
969
1012
|
if (!this.isConnected() && this.s.disconnectHandler != null) {
|
|
@@ -997,7 +1040,9 @@ Mongos.prototype.remove = function(ns, ops, options, callback) {
|
|
|
997
1040
|
(callback = options), (options = {}), (options = options || {});
|
|
998
1041
|
}
|
|
999
1042
|
|
|
1000
|
-
if (this.state === DESTROYED)
|
|
1043
|
+
if (this.state === DESTROYED) {
|
|
1044
|
+
return callback(new MongoError(f('topology was destroyed')));
|
|
1045
|
+
}
|
|
1001
1046
|
|
|
1002
1047
|
// Not connected but we have a disconnecthandler
|
|
1003
1048
|
if (!this.isConnected() && this.s.disconnectHandler != null) {
|
|
@@ -1036,7 +1081,10 @@ Mongos.prototype.command = function(ns, cmd, options, callback) {
|
|
|
1036
1081
|
(callback = options), (options = {}), (options = options || {});
|
|
1037
1082
|
}
|
|
1038
1083
|
|
|
1039
|
-
if (this.state === DESTROYED)
|
|
1084
|
+
if (this.state === DESTROYED) {
|
|
1085
|
+
return callback(new MongoError(f('topology was destroyed')));
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1040
1088
|
var self = this;
|
|
1041
1089
|
|
|
1042
1090
|
// Pick a proxy
|
|
@@ -277,27 +277,34 @@ function rexecuteOperations(self) {
|
|
|
277
277
|
}
|
|
278
278
|
|
|
279
279
|
function connectNewServers(self, servers, callback) {
|
|
280
|
+
// No new servers
|
|
281
|
+
if (servers.length === 0) {
|
|
282
|
+
return callback();
|
|
283
|
+
}
|
|
284
|
+
|
|
280
285
|
// Count lefts
|
|
281
286
|
var count = servers.length;
|
|
282
287
|
var error = null;
|
|
283
288
|
|
|
289
|
+
function done() {
|
|
290
|
+
count = count - 1;
|
|
291
|
+
if (count === 0) {
|
|
292
|
+
callback(error);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
284
296
|
// Handle events
|
|
285
297
|
var _handleEvent = function(self, event) {
|
|
286
298
|
return function(err) {
|
|
287
299
|
var _self = this;
|
|
288
|
-
count = count - 1;
|
|
289
300
|
|
|
290
301
|
// Destroyed
|
|
291
302
|
if (self.state === DESTROYED || self.state === UNREFERENCED) {
|
|
292
|
-
|
|
303
|
+
this.destroy({ force: true });
|
|
304
|
+
return done();
|
|
293
305
|
}
|
|
294
306
|
|
|
295
307
|
if (event === 'connect') {
|
|
296
|
-
// Destroyed
|
|
297
|
-
if (self.state === DESTROYED || self.state === UNREFERENCED) {
|
|
298
|
-
return _self.destroy({ force: true });
|
|
299
|
-
}
|
|
300
|
-
|
|
301
308
|
// Update the state
|
|
302
309
|
var result = self.s.replicaSetState.update(_self);
|
|
303
310
|
// Update the state with the new server
|
|
@@ -332,17 +339,10 @@ function connectNewServers(self, servers, callback) {
|
|
|
332
339
|
|
|
333
340
|
// Rexecute any stalled operation
|
|
334
341
|
rexecuteOperations(self);
|
|
335
|
-
|
|
336
|
-
// Are we done finish up callback
|
|
337
|
-
if (count === 0) {
|
|
338
|
-
callback(error);
|
|
339
|
-
}
|
|
342
|
+
done();
|
|
340
343
|
};
|
|
341
344
|
};
|
|
342
345
|
|
|
343
|
-
// No new servers
|
|
344
|
-
if (count === 0) return callback();
|
|
345
|
-
|
|
346
346
|
// Execute method
|
|
347
347
|
function execute(_server, i) {
|
|
348
348
|
setTimeout(function() {
|
|
@@ -351,6 +351,17 @@ function connectNewServers(self, servers, callback) {
|
|
|
351
351
|
return;
|
|
352
352
|
}
|
|
353
353
|
|
|
354
|
+
// remove existing connecting server if it's failed to connect, otherwise
|
|
355
|
+
// wait for that server to connect
|
|
356
|
+
const existingServerIdx = self.s.connectingServers.findIndex(s => s.name === _server);
|
|
357
|
+
if (existingServerIdx >= 0) {
|
|
358
|
+
const connectingServer = self.s.connectingServers[existingServerIdx];
|
|
359
|
+
connectingServer.destroy({ force: true });
|
|
360
|
+
|
|
361
|
+
self.s.connectingServers.splice(existingServerIdx, 1);
|
|
362
|
+
return done();
|
|
363
|
+
}
|
|
364
|
+
|
|
354
365
|
// Create a new server instance
|
|
355
366
|
var server = new Server(
|
|
356
367
|
Object.assign({}, self.s.options, {
|
|
@@ -378,6 +389,7 @@ function connectNewServers(self, servers, callback) {
|
|
|
378
389
|
// Command Monitoring events
|
|
379
390
|
relayEvents(server, self, ['commandStarted', 'commandSucceeded', 'commandFailed']);
|
|
380
391
|
|
|
392
|
+
self.s.connectingServers.push(server);
|
|
381
393
|
server.connect(self.s.connectOptions);
|
|
382
394
|
}, i);
|
|
383
395
|
}
|
|
@@ -951,6 +963,11 @@ ReplSet.prototype.auth = function(credentials, callback) {
|
|
|
951
963
|
* @method
|
|
952
964
|
*/
|
|
953
965
|
ReplSet.prototype.destroy = function(options, callback) {
|
|
966
|
+
if (typeof options === 'function') {
|
|
967
|
+
callback = options;
|
|
968
|
+
options = {};
|
|
969
|
+
}
|
|
970
|
+
|
|
954
971
|
options = options || {};
|
|
955
972
|
|
|
956
973
|
let destroyCount = this.s.connectingServers.length + 1; // +1 for the callback from `replicaSetState.destroy`
|
|
@@ -1202,6 +1219,7 @@ function executeWriteOperation(args, options, callback) {
|
|
|
1202
1219
|
|
|
1203
1220
|
// Per SDAM, remove primary from replicaset
|
|
1204
1221
|
if (self.s.replicaSetState.primary) {
|
|
1222
|
+
self.s.replicaSetState.primary.destroy();
|
|
1205
1223
|
self.s.replicaSetState.remove(self.s.replicaSetState.primary, { force: true });
|
|
1206
1224
|
}
|
|
1207
1225
|
|
|
@@ -1363,6 +1381,7 @@ ReplSet.prototype.command = function(ns, cmd, options, callback) {
|
|
|
1363
1381
|
|
|
1364
1382
|
// Per SDAM, remove primary from replicaset
|
|
1365
1383
|
if (this.s.replicaSetState.primary) {
|
|
1384
|
+
this.s.replicaSetState.primary.destroy();
|
|
1366
1385
|
this.s.replicaSetState.remove(this.s.replicaSetState.primary, { force: true });
|
|
1367
1386
|
}
|
|
1368
1387
|
|
|
@@ -391,7 +391,7 @@ ReplSetState.prototype.update = function(server) {
|
|
|
391
391
|
removeFrom(server, self.unknownServers);
|
|
392
392
|
|
|
393
393
|
// Destroy the instance
|
|
394
|
-
server.destroy();
|
|
394
|
+
server.destroy({ force: true });
|
|
395
395
|
|
|
396
396
|
// Set the type of topology we have
|
|
397
397
|
if (this.primary && !this.primary.equals(server)) {
|
|
@@ -555,7 +555,7 @@ ReplSetState.prototype.update = function(server) {
|
|
|
555
555
|
// Signal primary left
|
|
556
556
|
self.emit('left', 'primary', this.primary);
|
|
557
557
|
// Destroy the instance
|
|
558
|
-
self.primary.destroy();
|
|
558
|
+
self.primary.destroy({ force: true });
|
|
559
559
|
// Set the new instance
|
|
560
560
|
self.primary = server;
|
|
561
561
|
// Set the set information
|
|
@@ -607,7 +607,7 @@ ReplSetState.prototype.update = function(server) {
|
|
|
607
607
|
|
|
608
608
|
// Remove primary
|
|
609
609
|
if (this.primary && this.primary.name.toLowerCase() === serverName) {
|
|
610
|
-
server.destroy();
|
|
610
|
+
server.destroy({ force: true });
|
|
611
611
|
this.primary = null;
|
|
612
612
|
self.emit('left', 'primary', server);
|
|
613
613
|
}
|
|
@@ -659,7 +659,7 @@ ReplSetState.prototype.update = function(server) {
|
|
|
659
659
|
|
|
660
660
|
// Remove primary
|
|
661
661
|
if (this.primary && this.primary.name.toLowerCase() === serverName) {
|
|
662
|
-
server.destroy();
|
|
662
|
+
server.destroy({ force: true });
|
|
663
663
|
this.primary = null;
|
|
664
664
|
self.emit('left', 'primary', server);
|
|
665
665
|
}
|
|
@@ -674,7 +674,7 @@ ReplSetState.prototype.update = function(server) {
|
|
|
674
674
|
//
|
|
675
675
|
if (this.set[serverName] && this.set[serverName].type === ServerType.RSPrimary) {
|
|
676
676
|
self.emit('left', 'primary', this.primary);
|
|
677
|
-
this.primary.destroy();
|
|
677
|
+
this.primary.destroy({ force: true });
|
|
678
678
|
this.primary = null;
|
|
679
679
|
this.topologyType = TopologyType.ReplicaSetNoPrimary;
|
|
680
680
|
return false;
|
|
@@ -55,6 +55,10 @@ var serverAccounting = false;
|
|
|
55
55
|
var servers = {};
|
|
56
56
|
var BSON = retrieveBSON();
|
|
57
57
|
|
|
58
|
+
function topologyId(server) {
|
|
59
|
+
return server.s.parent == null ? server.id : server.s.parent.id;
|
|
60
|
+
}
|
|
61
|
+
|
|
58
62
|
/**
|
|
59
63
|
* Creates a new Server instance
|
|
60
64
|
* @class
|
|
@@ -151,8 +155,6 @@ var Server = function(options) {
|
|
|
151
155
|
// Monitoring timeout
|
|
152
156
|
monitoringInterval:
|
|
153
157
|
typeof options.monitoringInterval === 'number' ? options.monitoringInterval : 5000,
|
|
154
|
-
// Topology id
|
|
155
|
-
topologyId: -1,
|
|
156
158
|
compression: { compressors: createCompressionInfo(options) },
|
|
157
159
|
// Optional parent topology
|
|
158
160
|
parent: options.parent
|
|
@@ -486,14 +488,11 @@ Server.prototype.connect = function(options) {
|
|
|
486
488
|
|
|
487
489
|
// Emit toplogy opening event if not in topology
|
|
488
490
|
if (!self.s.inTopology) {
|
|
489
|
-
this.emit('topologyOpening', { topologyId: self
|
|
491
|
+
this.emit('topologyOpening', { topologyId: topologyId(self) });
|
|
490
492
|
}
|
|
491
493
|
|
|
492
494
|
// Emit opening server event
|
|
493
|
-
self.emit('serverOpening', {
|
|
494
|
-
topologyId: self.s.topologyId !== -1 ? self.s.topologyId : self.id,
|
|
495
|
-
address: self.name
|
|
496
|
-
});
|
|
495
|
+
self.emit('serverOpening', { topologyId: topologyId(self), address: self.name });
|
|
497
496
|
|
|
498
497
|
self.s.pool.connect();
|
|
499
498
|
};
|
|
@@ -843,6 +842,11 @@ Server.prototype.destroy = function(options, callback) {
|
|
|
843
842
|
return;
|
|
844
843
|
}
|
|
845
844
|
|
|
845
|
+
if (typeof options === 'function') {
|
|
846
|
+
callback = options;
|
|
847
|
+
options = {};
|
|
848
|
+
}
|
|
849
|
+
|
|
846
850
|
options = options || {};
|
|
847
851
|
var self = this;
|
|
848
852
|
|
|
@@ -878,14 +882,11 @@ Server.prototype.destroy = function(options, callback) {
|
|
|
878
882
|
|
|
879
883
|
// Emit opening server event
|
|
880
884
|
if (self.listeners('serverClosed').length > 0)
|
|
881
|
-
self.emit('serverClosed', {
|
|
882
|
-
topologyId: self.s.topologyId !== -1 ? self.s.topologyId : self.id,
|
|
883
|
-
address: self.name
|
|
884
|
-
});
|
|
885
|
+
self.emit('serverClosed', { topologyId: topologyId(self), address: self.name });
|
|
885
886
|
|
|
886
887
|
// Emit toplogy opening event if not in topology
|
|
887
888
|
if (self.listeners('topologyClosed').length > 0 && !self.s.inTopology) {
|
|
888
|
-
self.emit('topologyClosed', { topologyId: self
|
|
889
|
+
self.emit('topologyClosed', { topologyId: topologyId(self) });
|
|
889
890
|
}
|
|
890
891
|
|
|
891
892
|
if (self.s.logger.isDebug()) {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const os = require('os');
|
|
4
|
-
const f = require('util').format;
|
|
5
4
|
const ReadPreference = require('./read_preference');
|
|
6
5
|
const Buffer = require('safe-buffer').Buffer;
|
|
7
6
|
const TopologyType = require('../sdam/topology_description').TopologyType;
|
|
@@ -20,20 +19,19 @@ function emitSDAMEvent(self, event, description) {
|
|
|
20
19
|
}
|
|
21
20
|
|
|
22
21
|
// Get package.json variable
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
22
|
+
const driverVersion = require('../../../package.json').version;
|
|
23
|
+
const nodejsVersion = `'Node.js ${process.version}, ${os.endianness}`;
|
|
24
|
+
const type = os.type();
|
|
25
|
+
const name = process.platform;
|
|
26
|
+
const architecture = process.arch;
|
|
27
|
+
const release = os.release();
|
|
29
28
|
|
|
30
29
|
function createClientInfo(options) {
|
|
31
|
-
|
|
32
|
-
var clientInfo = options.clientInfo
|
|
30
|
+
const clientInfo = options.clientInfo
|
|
33
31
|
? clone(options.clientInfo)
|
|
34
32
|
: {
|
|
35
33
|
driver: {
|
|
36
|
-
name: 'nodejs
|
|
34
|
+
name: 'nodejs',
|
|
37
35
|
version: driverVersion
|
|
38
36
|
},
|
|
39
37
|
os: {
|
|
@@ -44,11 +42,8 @@ function createClientInfo(options) {
|
|
|
44
42
|
}
|
|
45
43
|
};
|
|
46
44
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
clientInfo.platform = f('%s, mongodb-core: %s', clientInfo.platform, driverVersion);
|
|
50
|
-
} else if (!clientInfo.platform) {
|
|
51
|
-
clientInfo.platform = nodejsversion;
|
|
45
|
+
if (options.useUnifiedTopology) {
|
|
46
|
+
clientInfo.platform = `${nodejsVersion} (${options.useUnifiedTopology ? 'unified' : 'legacy'})`;
|
|
52
47
|
}
|
|
53
48
|
|
|
54
49
|
// Do we have an application specific string
|
|
@@ -473,3 +468,4 @@ module.exports.Interval = Interval;
|
|
|
473
468
|
module.exports.Timeout = Timeout;
|
|
474
469
|
module.exports.isRetryableWritesSupported = isRetryableWritesSupported;
|
|
475
470
|
module.exports.getMMAPError = getMMAPError;
|
|
471
|
+
module.exports.topologyType = topologyType;
|
package/lib/core/uri_parser.js
CHANGED
|
@@ -534,6 +534,10 @@ function parseConnectionString(uri, options, callback) {
|
|
|
534
534
|
if (parsedOptions.auth.username) auth.username = parsedOptions.auth.username;
|
|
535
535
|
if (parsedOptions.auth.user) auth.username = parsedOptions.auth.user;
|
|
536
536
|
if (parsedOptions.auth.password) auth.password = parsedOptions.auth.password;
|
|
537
|
+
} else {
|
|
538
|
+
if (parsedOptions.username) auth.username = parsedOptions.username;
|
|
539
|
+
if (parsedOptions.user) auth.username = parsedOptions.user;
|
|
540
|
+
if (parsedOptions.password) auth.password = parsedOptions.password;
|
|
537
541
|
}
|
|
538
542
|
|
|
539
543
|
if (cap[4].split('?')[0].indexOf('@') !== -1) {
|
|
@@ -551,8 +555,8 @@ function parseConnectionString(uri, options, callback) {
|
|
|
551
555
|
return callback(new MongoParseError('Unescaped colon in authority section'));
|
|
552
556
|
}
|
|
553
557
|
|
|
554
|
-
auth.username = qs.unescape(authParts[0]);
|
|
555
|
-
auth.password = authParts[1] ? qs.unescape(authParts[1]) : null;
|
|
558
|
+
if (!auth.username) auth.username = qs.unescape(authParts[0]);
|
|
559
|
+
if (!auth.password) auth.password = authParts[1] ? qs.unescape(authParts[1]) : null;
|
|
556
560
|
}
|
|
557
561
|
|
|
558
562
|
let hostParsingError = null;
|
|
@@ -617,6 +621,8 @@ function parseConnectionString(uri, options, callback) {
|
|
|
617
621
|
|
|
618
622
|
if (result.auth && result.auth.db) {
|
|
619
623
|
result.defaultDatabase = result.auth.db;
|
|
624
|
+
} else {
|
|
625
|
+
result.defaultDatabase = 'test';
|
|
620
626
|
}
|
|
621
627
|
|
|
622
628
|
try {
|
package/lib/core/utils.js
CHANGED
|
@@ -150,7 +150,12 @@ function eachAsync(arr, eachFn, callback) {
|
|
|
150
150
|
}
|
|
151
151
|
|
|
152
152
|
for (let idx = 0; idx < length; ++idx) {
|
|
153
|
-
|
|
153
|
+
try {
|
|
154
|
+
eachFn(arr[idx], eachCallback);
|
|
155
|
+
} catch (err) {
|
|
156
|
+
callback(err);
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
154
159
|
}
|
|
155
160
|
}
|
|
156
161
|
|
|
@@ -158,6 +163,36 @@ function isUnifiedTopology(topology) {
|
|
|
158
163
|
return topology.description != null;
|
|
159
164
|
}
|
|
160
165
|
|
|
166
|
+
function arrayStrictEqual(arr, arr2) {
|
|
167
|
+
if (!Array.isArray(arr) || !Array.isArray(arr2)) {
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return arr.length === arr2.length && arr.every((elt, idx) => elt === arr2[idx]);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function tagsStrictEqual(tags, tags2) {
|
|
175
|
+
const tagsKeys = Object.keys(tags);
|
|
176
|
+
const tags2Keys = Object.keys(tags2);
|
|
177
|
+
return tagsKeys.length === tags2Keys.length && tagsKeys.every(key => tags2[key] === tags[key]);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function makeStateMachine(stateTable) {
|
|
181
|
+
return function stateTransition(target, newState) {
|
|
182
|
+
const legalStates = stateTable[target.s.state];
|
|
183
|
+
if (legalStates && legalStates.indexOf(newState) < 0) {
|
|
184
|
+
throw new TypeError(
|
|
185
|
+
`illegal state transition from [${
|
|
186
|
+
target.s.state
|
|
187
|
+
}] => [${newState}], allowed: [${legalStates}]`
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
target.emit('stateChanged', target.s.state, newState);
|
|
192
|
+
target.s.state = newState;
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
|
|
161
196
|
module.exports = {
|
|
162
197
|
uuidV4,
|
|
163
198
|
calculateDurationInMs,
|
|
@@ -168,5 +203,8 @@ module.exports = {
|
|
|
168
203
|
maxWireVersion,
|
|
169
204
|
isPromiseLike,
|
|
170
205
|
eachAsync,
|
|
171
|
-
isUnifiedTopology
|
|
206
|
+
isUnifiedTopology,
|
|
207
|
+
arrayStrictEqual,
|
|
208
|
+
tagsStrictEqual,
|
|
209
|
+
makeStateMachine
|
|
172
210
|
};
|
package/lib/cursor.js
CHANGED
|
@@ -543,7 +543,7 @@ class Cursor extends CoreCursor {
|
|
|
543
543
|
/**
|
|
544
544
|
* Set the batch size for the cursor.
|
|
545
545
|
* @method
|
|
546
|
-
* @param {number} value The
|
|
546
|
+
* @param {number} value The number of documents to return per batch. See {@link https://docs.mongodb.com/manual/reference/command/find/|find command documentation}.
|
|
547
547
|
* @throws {MongoError}
|
|
548
548
|
* @return {Cursor}
|
|
549
549
|
*/
|
package/lib/db.js
CHANGED
|
@@ -302,7 +302,7 @@ Db.prototype.command = function(command, options, callback) {
|
|
|
302
302
|
* @param {object} [options] Optional settings.
|
|
303
303
|
* @param {(ReadPreference|string)} [options.readPreference] The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
|
|
304
304
|
* @param {object} [options.cursor] Return the query as cursor, on 2.6 > it returns as a real cursor on pre 2.6 it returns as an emulated cursor.
|
|
305
|
-
* @param {number} [options.cursor.batchSize] The
|
|
305
|
+
* @param {number} [options.cursor.batchSize=1000] The number of documents to return per batch. See {@link https://docs.mongodb.com/manual/reference/command/aggregate|aggregation documentation}.
|
|
306
306
|
* @param {boolean} [options.explain=false] Explain returns the aggregation execution plan (requires mongodb 2.6 >).
|
|
307
307
|
* @param {boolean} [options.allowDiskUse=false] allowDiskUse lets the server know if it can use disk to store temporary results for the aggregation (requires mongodb 2.6 >).
|
|
308
308
|
* @param {number} [options.maxTimeMS] maxTimeMS specifies a cumulative time limit in milliseconds for processing operations on the cursor. MongoDB interrupts the operation at the earliest following interrupt point.
|
|
@@ -563,7 +563,7 @@ Db.prototype.stats = function(options, callback) {
|
|
|
563
563
|
* @param {object} [filter={}] Query to filter collections by
|
|
564
564
|
* @param {object} [options] Optional settings.
|
|
565
565
|
* @param {boolean} [options.nameOnly=false] Since 4.0: If true, will only return the collection name in the response, and will omit additional info
|
|
566
|
-
* @param {number} [options.batchSize] The batchSize for the returned command cursor or if pre 2.8 the systems batch collection
|
|
566
|
+
* @param {number} [options.batchSize=1000] The batchSize for the returned command cursor or if pre 2.8 the systems batch collection
|
|
567
567
|
* @param {(ReadPreference|string)} [options.readPreference] The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
|
|
568
568
|
* @param {ClientSession} [options.session] optional session to use for this operation
|
|
569
569
|
* @return {CommandCursor}
|
|
@@ -930,7 +930,7 @@ Db.prototype.unref = function() {
|
|
|
930
930
|
* @param {string} [options.fullDocument='default'] Allowed values: ‘default’, ‘updateLookup’. When set to ‘updateLookup’, the change stream will include both a delta describing the changes to the document, as well as a copy of the entire document that was changed from some time after the change occurred.
|
|
931
931
|
* @param {object} [options.resumeAfter] Specifies the logical starting point for the new change stream. This should be the _id field from a previously returned change stream document.
|
|
932
932
|
* @param {number} [options.maxAwaitTimeMS] The maximum amount of time for the server to wait on new documents to satisfy a change stream query
|
|
933
|
-
* @param {number} [options.batchSize] The number of documents to return per batch. See {@link https://docs.mongodb.com/manual/reference/command/aggregate|aggregation documentation}.
|
|
933
|
+
* @param {number} [options.batchSize=1000] The number of documents to return per batch. See {@link https://docs.mongodb.com/manual/reference/command/aggregate|aggregation documentation}.
|
|
934
934
|
* @param {object} [options.collation] Specify collation settings for operation. See {@link https://docs.mongodb.com/manual/reference/command/aggregate|aggregation documentation}.
|
|
935
935
|
* @param {ReadPreference} [options.readPreference] The read preference. Defaults to the read preference of the database. See {@link https://docs.mongodb.com/manual/reference/read-preference|read preference documentation}.
|
|
936
936
|
* @param {Timestamp} [options.startAtOperationTime] receive change events that occur after the specified timestamp
|
|
@@ -185,12 +185,19 @@ function doRead(_this) {
|
|
|
185
185
|
}
|
|
186
186
|
if (!doc) {
|
|
187
187
|
_this.push(null);
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
188
|
+
|
|
189
|
+
process.nextTick(() => {
|
|
190
|
+
_this.s.cursor.close(function(error) {
|
|
191
|
+
if (error) {
|
|
192
|
+
__handleError(_this, error);
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
_this.emit('close');
|
|
197
|
+
});
|
|
193
198
|
});
|
|
199
|
+
|
|
200
|
+
return;
|
|
194
201
|
}
|
|
195
202
|
|
|
196
203
|
var bytesRemaining = _this.s.file.length - _this.s.bytesRead;
|
|
@@ -198,7 +198,7 @@ function _delete(_this, id, callback) {
|
|
|
198
198
|
* @method
|
|
199
199
|
* @param {Object} filter
|
|
200
200
|
* @param {Object} [options] Optional settings for cursor
|
|
201
|
-
* @param {number} [options.batchSize]
|
|
201
|
+
* @param {number} [options.batchSize=1000] The number of documents to return per batch. See {@link https://docs.mongodb.com/manual/reference/command/find|find command documentation}.
|
|
202
202
|
* @param {number} [options.limit] Optional limit for cursor
|
|
203
203
|
* @param {number} [options.maxTimeMS] Optional maxTimeMS for cursor
|
|
204
204
|
* @param {boolean} [options.noCursorTimeout] Optionally set cursor's `noCursorTimeout` flag
|