mongodb 3.3.2 → 3.3.3
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 +38 -0
- package/lib/aggregation_cursor.js +1 -1
- package/lib/bulk/common.js +150 -73
- package/lib/bulk/ordered.js +1 -1
- package/lib/bulk/unordered.js +1 -0
- package/lib/change_stream.js +1 -1
- package/lib/collection.js +65 -14
- package/lib/command_cursor.js +1 -1
- package/lib/core/connection/connection.js +7 -3
- package/lib/core/connection/msg.js +3 -2
- package/lib/core/connection/pool.js +114 -143
- 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 +24 -4
- package/lib/core/sdam/topology.js +48 -20
- package/lib/core/sdam/topology_description.js +1 -1
- package/lib/core/topologies/mongos.js +72 -24
- package/lib/core/topologies/replset.js +8 -0
- package/lib/core/topologies/replset_state.js +5 -5
- package/lib/core/topologies/server.js +5 -0
- package/lib/core/topologies/shared.js +1 -0
- package/lib/core/uri_parser.js +8 -2
- package/lib/core/utils.js +6 -1
- package/lib/cursor.js +1 -1
- package/lib/db.js +3 -3
- package/lib/gridfs-stream/index.js +1 -1
- package/lib/mongo_client.js +2 -2
- package/lib/operations/connect.js +15 -12
- package/lib/operations/replace_one.js +1 -1
- package/package.json +9 -5
package/lib/collection.js
CHANGED
|
@@ -260,7 +260,7 @@ const DEPRECATED_FIND_OPTIONS = ['maxScan', 'fields', 'snapshot'];
|
|
|
260
260
|
* @param {boolean} [options.snapshot=false] DEPRECATED: Snapshot query.
|
|
261
261
|
* @param {boolean} [options.timeout=false] Specify if the cursor can timeout.
|
|
262
262
|
* @param {boolean} [options.tailable=false] Specify if the cursor is tailable.
|
|
263
|
-
* @param {number} [options.batchSize=
|
|
263
|
+
* @param {number} [options.batchSize=1000] Set the batchSize for the getMoreCommand when iterating over the query results.
|
|
264
264
|
* @param {boolean} [options.returnKey=false] Only return the index key.
|
|
265
265
|
* @param {number} [options.maxScan] DEPRECATED: Limit the number of items to scan.
|
|
266
266
|
* @param {number} [options.min] Set index bounds.
|
|
@@ -667,7 +667,7 @@ Collection.prototype.insert = deprecate(function(docs, options, callback) {
|
|
|
667
667
|
* @property {Object} upsertedId The upserted id.
|
|
668
668
|
* @property {ObjectId} upsertedId._id The upserted _id returned from the server.
|
|
669
669
|
* @property {Object} message
|
|
670
|
-
* @property {
|
|
670
|
+
* @property {object[]} [ops] In a response to {@link Collection#replaceOne replaceOne}, contains the new value of the document on the server. This is the same document that was originally passed in, and is only here for legacy purposes.
|
|
671
671
|
*/
|
|
672
672
|
|
|
673
673
|
/**
|
|
@@ -729,7 +729,7 @@ Collection.prototype.updateOne = function(filter, update, options, callback) {
|
|
|
729
729
|
* @param {boolean} [options.bypassDocumentValidation=false] Allow driver to bypass schema validation in MongoDB 3.2 or higher.
|
|
730
730
|
* @param {ClientSession} [options.session] optional session to use for this operation
|
|
731
731
|
* @param {Collection~updateWriteOpCallback} [callback] The command result callback
|
|
732
|
-
* @return {Promise<Collection~
|
|
732
|
+
* @return {Promise<Collection~updateWriteOpResult>} returns Promise if no callback passed
|
|
733
733
|
*/
|
|
734
734
|
Collection.prototype.replaceOne = function(filter, doc, options, callback) {
|
|
735
735
|
if (typeof options === 'function') (callback = options), (options = {});
|
|
@@ -759,7 +759,7 @@ Collection.prototype.replaceOne = function(filter, doc, options, callback) {
|
|
|
759
759
|
* @param {Array} [options.arrayFilters] optional list of array filters referenced in filtered positional operators
|
|
760
760
|
* @param {ClientSession} [options.session] optional session to use for this operation
|
|
761
761
|
* @param {Collection~updateWriteOpCallback} [callback] The command result callback
|
|
762
|
-
* @return {Promise<Collection~
|
|
762
|
+
* @return {Promise<Collection~updateWriteOpResult>} returns Promise if no callback passed
|
|
763
763
|
*/
|
|
764
764
|
Collection.prototype.updateMany = function(filter, update, options, callback) {
|
|
765
765
|
if (typeof options === 'function') (callback = options), (options = {});
|
|
@@ -985,7 +985,7 @@ Collection.prototype.save = deprecate(function(doc, options, callback) {
|
|
|
985
985
|
* @param {boolean} [options.snapshot=false] DEPRECATED: Snapshot query.
|
|
986
986
|
* @param {boolean} [options.timeout=false] Specify if the cursor can timeout.
|
|
987
987
|
* @param {boolean} [options.tailable=false] Specify if the cursor is tailable.
|
|
988
|
-
* @param {number} [options.batchSize=
|
|
988
|
+
* @param {number} [options.batchSize=1] Set the batchSize for the getMoreCommand when iterating over the query results.
|
|
989
989
|
* @param {boolean} [options.returnKey=false] Only return the index key.
|
|
990
990
|
* @param {number} [options.maxScan] DEPRECATED: Limit the number of items to scan.
|
|
991
991
|
* @param {number} [options.min] Set index bounds.
|
|
@@ -1119,7 +1119,7 @@ Collection.prototype.isCapped = function(options, callback) {
|
|
|
1119
1119
|
/**
|
|
1120
1120
|
* Creates an index on the db and collection collection.
|
|
1121
1121
|
* @method
|
|
1122
|
-
* @param {(string|object)} fieldOrSpec Defines the index.
|
|
1122
|
+
* @param {(string|array|object)} fieldOrSpec Defines the index.
|
|
1123
1123
|
* @param {object} [options] Optional settings.
|
|
1124
1124
|
* @param {(number|string)} [options.w] The write concern.
|
|
1125
1125
|
* @param {number} [options.wtimeout] The write concern timeout.
|
|
@@ -1138,6 +1138,25 @@ Collection.prototype.isCapped = function(options, callback) {
|
|
|
1138
1138
|
* @param {ClientSession} [options.session] optional session to use for this operation
|
|
1139
1139
|
* @param {Collection~resultCallback} [callback] The command result callback
|
|
1140
1140
|
* @return {Promise} returns Promise if no callback passed
|
|
1141
|
+
* @example
|
|
1142
|
+
* const collection = client.db('foo').collection('bar');
|
|
1143
|
+
*
|
|
1144
|
+
* await collection.createIndex({ a: 1, b: -1 });
|
|
1145
|
+
*
|
|
1146
|
+
* // Alternate syntax for { c: 1, d: -1 } that ensures order of indexes
|
|
1147
|
+
* await collection.createIndex([ [c, 1], [d, -1] ]);
|
|
1148
|
+
*
|
|
1149
|
+
* // Equivalent to { e: 1 }
|
|
1150
|
+
* await collection.createIndex('e');
|
|
1151
|
+
*
|
|
1152
|
+
* // Equivalent to { f: 1, g: 1 }
|
|
1153
|
+
* await collection.createIndex(['f', 'g'])
|
|
1154
|
+
*
|
|
1155
|
+
* // Equivalent to { h: 1, i: -1 }
|
|
1156
|
+
* await collection.createIndex([ { h: 1 }, { i: -1 } ]);
|
|
1157
|
+
*
|
|
1158
|
+
* // Equivalent to { j: 1, k: -1, l: 2d }
|
|
1159
|
+
* await collection.createIndex(['j', ['k', -1], { l: '2d' }])
|
|
1141
1160
|
*/
|
|
1142
1161
|
Collection.prototype.createIndex = function(fieldOrSpec, options, callback) {
|
|
1143
1162
|
if (typeof options === 'function') (callback = options), (options = {});
|
|
@@ -1153,16 +1172,43 @@ Collection.prototype.createIndex = function(fieldOrSpec, options, callback) {
|
|
|
1153
1172
|
return executeOperation(this.s.topology, createIndexOperation, callback);
|
|
1154
1173
|
};
|
|
1155
1174
|
|
|
1175
|
+
/**
|
|
1176
|
+
* @typedef {object} Collection~IndexDefinition
|
|
1177
|
+
* @description A definition for an index. Used by the createIndex command.
|
|
1178
|
+
* @see https://docs.mongodb.com/manual/reference/command/createIndexes/
|
|
1179
|
+
*/
|
|
1180
|
+
|
|
1156
1181
|
/**
|
|
1157
1182
|
* Creates multiple indexes in the collection, this method is only supported for
|
|
1158
1183
|
* MongoDB 2.6 or higher. Earlier version of MongoDB will throw a command not supported
|
|
1159
|
-
* error.
|
|
1184
|
+
* error.
|
|
1185
|
+
*
|
|
1186
|
+
* **Note**: Unlike {@link Collection#createIndex createIndex}, this function takes in raw index specifications.
|
|
1187
|
+
* Index specifications are defined {@link http://docs.mongodb.org/manual/reference/command/createIndexes/ here}.
|
|
1188
|
+
*
|
|
1160
1189
|
* @method
|
|
1161
|
-
* @param {
|
|
1190
|
+
* @param {Collection~IndexDefinition[]} indexSpecs An array of index specifications to be created
|
|
1162
1191
|
* @param {Object} [options] Optional settings
|
|
1163
1192
|
* @param {ClientSession} [options.session] optional session to use for this operation
|
|
1164
1193
|
* @param {Collection~resultCallback} [callback] The command result callback
|
|
1165
1194
|
* @return {Promise} returns Promise if no callback passed
|
|
1195
|
+
* @example
|
|
1196
|
+
* const collection = client.db('foo').collection('bar');
|
|
1197
|
+
* await collection.createIndexes([
|
|
1198
|
+
* // Simple index on field fizz
|
|
1199
|
+
* {
|
|
1200
|
+
* key: { fizz: 1 },
|
|
1201
|
+
* }
|
|
1202
|
+
* // wildcard index
|
|
1203
|
+
* {
|
|
1204
|
+
* key: { '$**': 1 }
|
|
1205
|
+
* },
|
|
1206
|
+
* // named index on darmok and jalad
|
|
1207
|
+
* {
|
|
1208
|
+
* key: { darmok: 1, jalad: -1 }
|
|
1209
|
+
* name: 'tanagra'
|
|
1210
|
+
* }
|
|
1211
|
+
* ]);
|
|
1166
1212
|
*/
|
|
1167
1213
|
Collection.prototype.createIndexes = function(indexSpecs, options, callback) {
|
|
1168
1214
|
if (typeof options === 'function') (callback = options), (options = {});
|
|
@@ -1256,7 +1302,7 @@ Collection.prototype.reIndex = function(options, callback) {
|
|
|
1256
1302
|
*
|
|
1257
1303
|
* @method
|
|
1258
1304
|
* @param {object} [options] Optional settings.
|
|
1259
|
-
* @param {number} [options.batchSize] The batchSize for the returned command cursor or if pre 2.8 the systems batch collection
|
|
1305
|
+
* @param {number} [options.batchSize=1000] The batchSize for the returned command cursor or if pre 2.8 the systems batch collection
|
|
1260
1306
|
* @param {(ReadPreference|string)} [options.readPreference] The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
|
|
1261
1307
|
* @param {ClientSession} [options.session] optional session to use for this operation
|
|
1262
1308
|
* @return {CommandCursor}
|
|
@@ -1355,7 +1401,12 @@ Collection.prototype.indexInformation = function(options, callback) {
|
|
|
1355
1401
|
*/
|
|
1356
1402
|
|
|
1357
1403
|
/**
|
|
1358
|
-
*
|
|
1404
|
+
* An estimated count of matching documents in the db to a query.
|
|
1405
|
+
*
|
|
1406
|
+
* **NOTE:** This method has been deprecated, since it does not provide an accurate count of the documents
|
|
1407
|
+
* in a collection. To obtain an accurate count of documents in the collection, use {@link Collection#countDocuments countDocuments}.
|
|
1408
|
+
* To obtain an estimated count of all documents in the collection, use {@link Collection#estimatedDocumentCount estimatedDocumentCount}.
|
|
1409
|
+
*
|
|
1359
1410
|
* @method
|
|
1360
1411
|
* @param {object} [query={}] The query for the count.
|
|
1361
1412
|
* @param {object} [options] Optional settings.
|
|
@@ -1510,7 +1561,7 @@ Collection.prototype.stats = function(options, callback) {
|
|
|
1510
1561
|
/**
|
|
1511
1562
|
* @typedef {Object} Collection~findAndModifyWriteOpResult
|
|
1512
1563
|
* @property {object} value Document returned from the `findAndModify` command. If no documents were found, `value` will be `null` by default (`returnOriginal: true`), even if a document was upserted; if `returnOriginal` was false, the upserted document will be returned in that case.
|
|
1513
|
-
* @property {object} lastErrorObject The raw lastErrorObject returned from the command.
|
|
1564
|
+
* @property {object} lastErrorObject The raw lastErrorObject returned from the command. See {@link https://docs.mongodb.com/manual/reference/command/findAndModify/index.html#lasterrorobject|findAndModify command documentation}.
|
|
1514
1565
|
* @property {Number} ok Is 1 if the command executed correctly.
|
|
1515
1566
|
*/
|
|
1516
1567
|
|
|
@@ -1716,7 +1767,7 @@ Collection.prototype.findAndRemove = deprecate(function(query, sort, options, ca
|
|
|
1716
1767
|
* @param {object} [options] Optional settings.
|
|
1717
1768
|
* @param {(ReadPreference|string)} [options.readPreference] The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
|
|
1718
1769
|
* @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.
|
|
1719
|
-
* @param {number} [options.cursor.batchSize] The
|
|
1770
|
+
* @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}.
|
|
1720
1771
|
* @param {boolean} [options.explain=false] Explain returns the aggregation execution plan (requires mongodb 2.6 >).
|
|
1721
1772
|
* @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 >).
|
|
1722
1773
|
* @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.
|
|
@@ -1792,7 +1843,7 @@ Collection.prototype.aggregate = function(pipeline, options, callback) {
|
|
|
1792
1843
|
* @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.
|
|
1793
1844
|
* @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.
|
|
1794
1845
|
* @param {number} [options.maxAwaitTimeMS] The maximum amount of time for the server to wait on new documents to satisfy a change stream query
|
|
1795
|
-
* @param {number} [options.batchSize] The number of documents to return per batch. See {@link https://docs.mongodb.com/manual/reference/command/aggregate|aggregation documentation}.
|
|
1846
|
+
* @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}.
|
|
1796
1847
|
* @param {object} [options.collation] Specify collation settings for operation. See {@link https://docs.mongodb.com/manual/reference/command/aggregate|aggregation documentation}.
|
|
1797
1848
|
* @param {ReadPreference} [options.readPreference] The read preference. Defaults to the read preference of the database or collection. See {@link https://docs.mongodb.com/manual/reference/read-preference|read preference documentation}.
|
|
1798
1849
|
* @param {Timestamp} [options.startAtOperationTime] receive change events that occur after the specified timestamp
|
|
@@ -1825,7 +1876,7 @@ Collection.prototype.watch = function(pipeline, options) {
|
|
|
1825
1876
|
* @method
|
|
1826
1877
|
* @param {object} [options] Optional settings.
|
|
1827
1878
|
* @param {(ReadPreference|string)} [options.readPreference] The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
|
|
1828
|
-
* @param {number} [options.batchSize] Set the batchSize for the getMoreCommand when iterating over the query results.
|
|
1879
|
+
* @param {number} [options.batchSize=1000] Set the batchSize for the getMoreCommand when iterating over the query results.
|
|
1829
1880
|
* @param {number} [options.numCursors=1] The maximum number of parallel command cursors to return (the number of returned cursors will be in the range 1:numCursors)
|
|
1830
1881
|
* @param {boolean} [options.raw=false] Return all BSON documents as Raw Buffer documents.
|
|
1831
1882
|
* @param {Collection~parallelCollectionScanCallback} [callback] The command result callback
|
package/lib/command_cursor.js
CHANGED
|
@@ -90,7 +90,7 @@ class CommandCursor extends Cursor {
|
|
|
90
90
|
/**
|
|
91
91
|
* Set the batch size for the cursor.
|
|
92
92
|
* @method
|
|
93
|
-
* @param {number} value The
|
|
93
|
+
* @param {number} value The number of documents to return per batch. See {@link https://docs.mongodb.com/manual/reference/command/find/|find command documentation}.
|
|
94
94
|
* @throws {MongoError}
|
|
95
95
|
* @return {CommandCursor}
|
|
96
96
|
*/
|
|
@@ -56,10 +56,13 @@ class Connection extends EventEmitter {
|
|
|
56
56
|
/**
|
|
57
57
|
* Creates a new Connection instance
|
|
58
58
|
*
|
|
59
|
+
* **NOTE**: Internal class, do not instantiate directly
|
|
60
|
+
*
|
|
59
61
|
* @param {Socket} socket The socket this connection wraps
|
|
60
|
-
* @param {Object}
|
|
61
|
-
* @param {
|
|
62
|
-
* @param {
|
|
62
|
+
* @param {Object} options Various settings
|
|
63
|
+
* @param {object} options.bson An implementation of bson serialize and deserialize
|
|
64
|
+
* @param {string} [options.host='localhost'] The host the socket is connected to
|
|
65
|
+
* @param {number} [options.port=27017] The port used for the socket connection
|
|
63
66
|
* @param {boolean} [options.keepAlive=true] TCP Connection keep alive enabled
|
|
64
67
|
* @param {number} [options.keepAliveInitialDelay=300000] Initial delay before TCP keep alive enabled
|
|
65
68
|
* @param {number} [options.connectionTimeout=30000] TCP Connection timeout setting
|
|
@@ -67,6 +70,7 @@ class Connection extends EventEmitter {
|
|
|
67
70
|
* @param {boolean} [options.promoteLongs] Convert Long values from the db into Numbers if they fit into 53 bits
|
|
68
71
|
* @param {boolean} [options.promoteValues] Promotes BSON values to native types where possible, set to false to only receive wrapper types.
|
|
69
72
|
* @param {boolean} [options.promoteBuffers] Promotes Binary BSON values to native Node Buffers.
|
|
73
|
+
* @param {number} [options.maxBsonMessageSize=0x4000000] Largest possible size of a BSON message (for legacy purposes)
|
|
70
74
|
*/
|
|
71
75
|
constructor(socket, options) {
|
|
72
76
|
super();
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
// [uint32 checksum;]
|
|
28
28
|
// };
|
|
29
29
|
|
|
30
|
+
const Buffer = require('safe-buffer').Buffer;
|
|
30
31
|
const opcodes = require('../wireprotocol/shared').opcodes;
|
|
31
32
|
const databaseNamespace = require('../wireprotocol/shared').databaseNamespace;
|
|
32
33
|
const ReadPreference = require('../topologies/read_preference');
|
|
@@ -90,7 +91,7 @@ class Msg {
|
|
|
90
91
|
flags |= OPTS_EXHAUST_ALLOWED;
|
|
91
92
|
}
|
|
92
93
|
|
|
93
|
-
const header =
|
|
94
|
+
const header = Buffer.alloc(
|
|
94
95
|
4 * 4 + // Header
|
|
95
96
|
4 // Flags
|
|
96
97
|
);
|
|
@@ -110,7 +111,7 @@ class Msg {
|
|
|
110
111
|
}
|
|
111
112
|
|
|
112
113
|
makeDocumentSegment(buffers, document) {
|
|
113
|
-
const payloadTypeBuffer =
|
|
114
|
+
const payloadTypeBuffer = Buffer.alloc(1);
|
|
114
115
|
payloadTypeBuffer[0] = 0;
|
|
115
116
|
|
|
116
117
|
const documentBuffer = this.serializeBson(document);
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
const inherits = require('util').inherits;
|
|
4
4
|
const EventEmitter = require('events').EventEmitter;
|
|
5
5
|
const MongoError = require('../error').MongoError;
|
|
6
|
-
const
|
|
6
|
+
const MongoTimeoutError = require('../error').MongoTimeoutError;
|
|
7
7
|
const MongoWriteConcernError = require('../error').MongoWriteConcernError;
|
|
8
8
|
const Logger = require('./logger');
|
|
9
9
|
const f = require('util').format;
|
|
@@ -60,7 +60,7 @@ var _id = 0;
|
|
|
60
60
|
* @param {Buffer} [options.crl] SSL Certificate revocation store binary buffer
|
|
61
61
|
* @param {Buffer} [options.cert] SSL Certificate binary buffer
|
|
62
62
|
* @param {Buffer} [options.key] SSL Key file binary buffer
|
|
63
|
-
* @param {string} [options.
|
|
63
|
+
* @param {string} [options.passphrase] SSL Certificate pass phrase
|
|
64
64
|
* @param {boolean} [options.rejectUnauthorized=false] Reject unauthorized server certificates
|
|
65
65
|
* @param {boolean} [options.promoteLongs=true] Convert Long values from the db into Numbers if they fit into 53 bits
|
|
66
66
|
* @param {boolean} [options.promoteValues=true] Promotes BSON values to native types where possible, set to false to only receive wrapper types.
|
|
@@ -103,7 +103,7 @@ var Pool = function(topology, options) {
|
|
|
103
103
|
crl: null,
|
|
104
104
|
cert: null,
|
|
105
105
|
key: null,
|
|
106
|
-
|
|
106
|
+
passphrase: null,
|
|
107
107
|
rejectUnauthorized: false,
|
|
108
108
|
promoteLongs: true,
|
|
109
109
|
promoteValues: true,
|
|
@@ -113,7 +113,9 @@ var Pool = function(topology, options) {
|
|
|
113
113
|
reconnectInterval: 1000,
|
|
114
114
|
reconnectTries: 30,
|
|
115
115
|
// Enable domains
|
|
116
|
-
domainsEnabled: false
|
|
116
|
+
domainsEnabled: false,
|
|
117
|
+
// feature flag for determining if we are running with the unified topology or not
|
|
118
|
+
legacyCompatMode: true
|
|
117
119
|
},
|
|
118
120
|
options
|
|
119
121
|
);
|
|
@@ -123,6 +125,7 @@ var Pool = function(topology, options) {
|
|
|
123
125
|
// Current reconnect retries
|
|
124
126
|
this.retriesLeft = this.options.reconnectTries;
|
|
125
127
|
this.reconnectId = null;
|
|
128
|
+
this.reconnectError = null;
|
|
126
129
|
// No bson parser passed in
|
|
127
130
|
if (
|
|
128
131
|
!options.bson ||
|
|
@@ -146,9 +149,6 @@ var Pool = function(topology, options) {
|
|
|
146
149
|
// Operation work queue
|
|
147
150
|
this.queue = [];
|
|
148
151
|
|
|
149
|
-
// Contains the reconnect connection
|
|
150
|
-
this.reconnectConnection = null;
|
|
151
|
-
|
|
152
152
|
// Number of consecutive timeouts caught
|
|
153
153
|
this.numberOfConsecutiveTimeouts = 0;
|
|
154
154
|
// Current pool Index
|
|
@@ -214,7 +214,6 @@ function resetPoolState(pool) {
|
|
|
214
214
|
pool.availableConnections = [];
|
|
215
215
|
pool.connectingConnections = 0;
|
|
216
216
|
pool.executing = false;
|
|
217
|
-
pool.reconnectConnection = null;
|
|
218
217
|
pool.numberOfConsecutiveTimeouts = 0;
|
|
219
218
|
pool.connectionIndex = 0;
|
|
220
219
|
pool.retriesLeft = pool.options.reconnectTries;
|
|
@@ -293,73 +292,62 @@ function connectionFailureHandler(pool, event, err, conn) {
|
|
|
293
292
|
|
|
294
293
|
// Start reconnection attempts
|
|
295
294
|
if (!pool.reconnectId && pool.options.reconnect) {
|
|
295
|
+
pool.reconnectError = err;
|
|
296
296
|
pool.reconnectId = setTimeout(attemptReconnect(pool), pool.options.reconnectInterval);
|
|
297
297
|
}
|
|
298
298
|
|
|
299
299
|
// Do we need to do anything to maintain the minimum pool size
|
|
300
300
|
const totalConnections = totalConnectionCount(pool);
|
|
301
301
|
if (totalConnections < pool.minSize) {
|
|
302
|
-
|
|
302
|
+
createConnection(pool);
|
|
303
303
|
}
|
|
304
304
|
}
|
|
305
305
|
|
|
306
|
-
function attemptReconnect(
|
|
306
|
+
function attemptReconnect(pool, callback) {
|
|
307
307
|
return function() {
|
|
308
|
-
|
|
309
|
-
|
|
308
|
+
pool.emit('attemptReconnect', pool);
|
|
309
|
+
|
|
310
|
+
if (pool.state === DESTROYED || pool.state === DESTROYING) {
|
|
311
|
+
if (typeof callback === 'function') {
|
|
312
|
+
callback(new MongoError('Cannot create connection when pool is destroyed'));
|
|
313
|
+
}
|
|
310
314
|
|
|
311
|
-
// We are connected do not try again
|
|
312
|
-
if (self.isConnected()) {
|
|
313
|
-
self.reconnectId = null;
|
|
314
315
|
return;
|
|
315
316
|
}
|
|
316
317
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
318
|
+
pool.retriesLeft = pool.retriesLeft - 1;
|
|
319
|
+
if (pool.retriesLeft <= 0) {
|
|
320
|
+
pool.destroy();
|
|
320
321
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
if (self.retriesLeft <= 0) {
|
|
328
|
-
self.destroy();
|
|
329
|
-
self.emit(
|
|
330
|
-
'reconnectFailed',
|
|
331
|
-
new MongoNetworkError(
|
|
332
|
-
f(
|
|
333
|
-
'failed to reconnect after %s attempts with interval %s ms',
|
|
334
|
-
self.options.reconnectTries,
|
|
335
|
-
self.options.reconnectInterval
|
|
336
|
-
)
|
|
337
|
-
)
|
|
338
|
-
);
|
|
339
|
-
} else {
|
|
340
|
-
self.reconnectId = setTimeout(attemptReconnect(self), self.options.reconnectInterval);
|
|
341
|
-
}
|
|
322
|
+
const error = new MongoTimeoutError(
|
|
323
|
+
`failed to reconnect after ${pool.options.reconnectTries} attempts with interval ${
|
|
324
|
+
pool.options.reconnectInterval
|
|
325
|
+
} ms`,
|
|
326
|
+
pool.reconnectError
|
|
327
|
+
);
|
|
342
328
|
|
|
343
|
-
|
|
329
|
+
pool.emit('reconnectFailed', error);
|
|
330
|
+
if (typeof callback === 'function') {
|
|
331
|
+
callback(error);
|
|
344
332
|
}
|
|
345
333
|
|
|
346
|
-
|
|
347
|
-
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// clear the reconnect id on retry
|
|
338
|
+
pool.reconnectId = null;
|
|
339
|
+
|
|
340
|
+
// now retry creating a connection
|
|
341
|
+
createConnection(pool, (err, conn) => {
|
|
342
|
+
if (err == null) {
|
|
343
|
+
pool.reconnectId = null;
|
|
344
|
+
pool.retriesLeft = pool.options.reconnectTries;
|
|
345
|
+
pool.emit('reconnect', pool);
|
|
348
346
|
}
|
|
349
347
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
connection.on('close', self._connectionCloseHandler);
|
|
354
|
-
connection.on('timeout', self._connectionTimeoutHandler);
|
|
355
|
-
connection.on('parseError', self._connectionParseErrorHandler);
|
|
356
|
-
connection.on('message', self._messageHandler);
|
|
357
|
-
|
|
358
|
-
self.retriesLeft = self.options.reconnectTries;
|
|
359
|
-
self.availableConnections.push(connection);
|
|
360
|
-
self.reconnectConnection = null;
|
|
361
|
-
self.emit('reconnect', self);
|
|
362
|
-
_execute(self)();
|
|
348
|
+
if (typeof callback === 'function') {
|
|
349
|
+
callback(err, conn);
|
|
350
|
+
}
|
|
363
351
|
});
|
|
364
352
|
};
|
|
365
353
|
}
|
|
@@ -564,64 +552,26 @@ Pool.prototype.connect = function() {
|
|
|
564
552
|
throw new MongoError('connection in unlawful state ' + this.state);
|
|
565
553
|
}
|
|
566
554
|
|
|
567
|
-
const self = this;
|
|
568
555
|
stateTransition(this, CONNECTING);
|
|
569
|
-
|
|
570
|
-
self.connectingConnections++;
|
|
571
|
-
connect(self.options, (err, connection) => {
|
|
572
|
-
self.connectingConnections--;
|
|
573
|
-
|
|
556
|
+
createConnection(this, (err, conn) => {
|
|
574
557
|
if (err) {
|
|
575
|
-
if (
|
|
576
|
-
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
if (self.state === CONNECTING) {
|
|
580
|
-
self.emit('error', err);
|
|
558
|
+
if (this.state === CONNECTING) {
|
|
559
|
+
this.emit('error', err);
|
|
581
560
|
}
|
|
582
561
|
|
|
562
|
+
this.destroy();
|
|
583
563
|
return;
|
|
584
564
|
}
|
|
585
565
|
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
// attach event handlers
|
|
591
|
-
connection.on('error', self._connectionErrorHandler);
|
|
592
|
-
connection.on('close', self._connectionCloseHandler);
|
|
593
|
-
connection.on('timeout', self._connectionTimeoutHandler);
|
|
594
|
-
connection.on('parseError', self._connectionParseErrorHandler);
|
|
595
|
-
connection.on('message', self._messageHandler);
|
|
596
|
-
|
|
597
|
-
// If we are in a topology, delegate the auth to it
|
|
598
|
-
// This is to avoid issues where we would auth against an
|
|
599
|
-
// arbiter
|
|
600
|
-
if (self.options.inTopology) {
|
|
601
|
-
stateTransition(self, CONNECTED);
|
|
602
|
-
self.availableConnections.push(connection);
|
|
603
|
-
return self.emit('connect', self, connection);
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
if (self.state === DESTROYED || self.state === DESTROYING) {
|
|
607
|
-
return self.destroy();
|
|
608
|
-
}
|
|
609
|
-
|
|
610
|
-
if (err) {
|
|
611
|
-
self.destroy();
|
|
612
|
-
return self.emit('error', err);
|
|
613
|
-
}
|
|
566
|
+
stateTransition(this, CONNECTED);
|
|
567
|
+
this.emit('connect', this, conn);
|
|
614
568
|
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
for (let i = 0; i < self.minSize; i++) {
|
|
620
|
-
_createConnection(self);
|
|
569
|
+
// create min connections
|
|
570
|
+
if (this.minSize) {
|
|
571
|
+
for (let i = 0; i < this.minSize; i++) {
|
|
572
|
+
createConnection(this);
|
|
621
573
|
}
|
|
622
574
|
}
|
|
623
|
-
|
|
624
|
-
self.emit('connect', self, connection);
|
|
625
575
|
});
|
|
626
576
|
};
|
|
627
577
|
|
|
@@ -718,12 +668,6 @@ Pool.prototype.destroy = function(force, callback) {
|
|
|
718
668
|
clearTimeout(this.reconnectId);
|
|
719
669
|
}
|
|
720
670
|
|
|
721
|
-
// If we have a reconnect connection running, close
|
|
722
|
-
// immediately
|
|
723
|
-
if (this.reconnectConnection) {
|
|
724
|
-
this.reconnectConnection.destroy();
|
|
725
|
-
}
|
|
726
|
-
|
|
727
671
|
// Wait for the operations to drain before we close the pool
|
|
728
672
|
function checkStatus() {
|
|
729
673
|
flushMonitoringOperations(self.queue);
|
|
@@ -782,7 +726,7 @@ Pool.prototype.reset = function(callback) {
|
|
|
782
726
|
resetPoolState(this);
|
|
783
727
|
|
|
784
728
|
// create an initial connection, and kick off execution again
|
|
785
|
-
|
|
729
|
+
createConnection(this);
|
|
786
730
|
|
|
787
731
|
if (typeof callback === 'function') {
|
|
788
732
|
callback(null, null);
|
|
@@ -996,55 +940,82 @@ function removeConnection(self, connection) {
|
|
|
996
940
|
if (remove(connection, self.inUseConnections)) return;
|
|
997
941
|
}
|
|
998
942
|
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
943
|
+
function createConnection(pool, callback) {
|
|
944
|
+
if (pool.state === DESTROYED || pool.state === DESTROYING) {
|
|
945
|
+
if (typeof callback === 'function') {
|
|
946
|
+
callback(new MongoError('Cannot create connection when pool is destroyed'));
|
|
947
|
+
}
|
|
948
|
+
|
|
1002
949
|
return;
|
|
1003
950
|
}
|
|
1004
951
|
|
|
1005
|
-
|
|
1006
|
-
connect(
|
|
1007
|
-
|
|
952
|
+
pool.connectingConnections++;
|
|
953
|
+
connect(pool.options, (err, connection) => {
|
|
954
|
+
pool.connectingConnections--;
|
|
1008
955
|
|
|
1009
956
|
if (err) {
|
|
1010
|
-
if (
|
|
1011
|
-
|
|
957
|
+
if (pool.logger.isDebug()) {
|
|
958
|
+
pool.logger.debug(`connection attempt failed with error [${JSON.stringify(err)}]`);
|
|
1012
959
|
}
|
|
1013
960
|
|
|
1014
|
-
if (
|
|
1015
|
-
|
|
961
|
+
if (pool.options.legacyCompatMode === false) {
|
|
962
|
+
// The unified topology uses the reported `error` from a pool to track what error
|
|
963
|
+
// reason is returned to the user during selection timeout. We only want to emit
|
|
964
|
+
// this if the pool is active because the listeners are removed on destruction.
|
|
965
|
+
if (pool.state !== DESTROYED && pool.state !== DESTROYING) {
|
|
966
|
+
pool.emit('error', err);
|
|
967
|
+
}
|
|
1016
968
|
}
|
|
1017
969
|
|
|
1018
|
-
|
|
1019
|
-
|
|
970
|
+
// check if reconnect is enabled, and attempt retry if so
|
|
971
|
+
if (!pool.reconnectId && pool.options.reconnect) {
|
|
972
|
+
if (pool.state === CONNECTING && pool.options.legacyCompatMode) {
|
|
973
|
+
callback(err);
|
|
974
|
+
return;
|
|
975
|
+
}
|
|
1020
976
|
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
977
|
+
pool.reconnectError = err;
|
|
978
|
+
pool.reconnectId = setTimeout(
|
|
979
|
+
attemptReconnect(pool, callback),
|
|
980
|
+
pool.options.reconnectInterval
|
|
981
|
+
);
|
|
982
|
+
|
|
983
|
+
return;
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
if (typeof callback === 'function') {
|
|
987
|
+
callback(err);
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
return;
|
|
1024
991
|
}
|
|
1025
992
|
|
|
1026
|
-
connection
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
993
|
+
// the pool might have been closed since we started creating the connection
|
|
994
|
+
if (pool.state === DESTROYED || pool.state === DESTROYING) {
|
|
995
|
+
if (typeof callback === 'function') {
|
|
996
|
+
callback(new MongoError('Pool was destroyed after connection creation'));
|
|
997
|
+
}
|
|
1031
998
|
|
|
1032
|
-
|
|
1033
|
-
return
|
|
999
|
+
connection.destroy();
|
|
1000
|
+
return;
|
|
1034
1001
|
}
|
|
1035
1002
|
|
|
1036
|
-
//
|
|
1037
|
-
|
|
1003
|
+
// otherwise, connect relevant event handlers and add it to our available connections
|
|
1004
|
+
connection.on('error', pool._connectionErrorHandler);
|
|
1005
|
+
connection.on('close', pool._connectionCloseHandler);
|
|
1006
|
+
connection.on('timeout', pool._connectionTimeoutHandler);
|
|
1007
|
+
connection.on('parseError', pool._connectionParseErrorHandler);
|
|
1008
|
+
connection.on('message', pool._messageHandler);
|
|
1038
1009
|
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1010
|
+
pool.availableConnections.push(connection);
|
|
1011
|
+
|
|
1012
|
+
// if a callback was provided, return the connection
|
|
1013
|
+
if (typeof callback === 'function') {
|
|
1014
|
+
callback(null, connection);
|
|
1042
1015
|
}
|
|
1043
1016
|
|
|
1044
|
-
//
|
|
1045
|
-
|
|
1046
|
-
// Execute any work waiting
|
|
1047
|
-
_execute(self)();
|
|
1017
|
+
// immediately execute any waiting work
|
|
1018
|
+
_execute(pool)();
|
|
1048
1019
|
});
|
|
1049
1020
|
}
|
|
1050
1021
|
|
|
@@ -1146,7 +1117,7 @@ function _execute(self) {
|
|
|
1146
1117
|
// Attempt to grow the pool if it's not yet maxsize
|
|
1147
1118
|
if (totalConnections < self.options.size && self.queue.length > 0) {
|
|
1148
1119
|
// Create a new connection
|
|
1149
|
-
|
|
1120
|
+
createConnection(self);
|
|
1150
1121
|
}
|
|
1151
1122
|
|
|
1152
1123
|
// Re-execute the operation
|
|
@@ -1166,7 +1137,7 @@ function _execute(self) {
|
|
|
1166
1137
|
// Lets put the workItem back on the list
|
|
1167
1138
|
self.queue.unshift(workItem);
|
|
1168
1139
|
// Create a new connection
|
|
1169
|
-
|
|
1140
|
+
createConnection(self);
|
|
1170
1141
|
// Break from the loop
|
|
1171
1142
|
break;
|
|
1172
1143
|
}
|
package/lib/core/cursor.js
CHANGED
|
@@ -68,7 +68,7 @@ class CoreCursor extends Readable {
|
|
|
68
68
|
* @param {string} ns The MongoDB fully qualified namespace (ex: db1.collection1)
|
|
69
69
|
* @param {{object}|Long} cmd The selector (can be a command or a cursorId)
|
|
70
70
|
* @param {object} [options=null] Optional settings.
|
|
71
|
-
* @param {object} [options.batchSize=1000]
|
|
71
|
+
* @param {object} [options.batchSize=1000] The number of documents to return per batch. See {@link https://docs.mongodb.com/manual/reference/command/find/| find command documentation} and {@link https://docs.mongodb.com/manual/reference/command/aggregate|aggregation documentation}.
|
|
72
72
|
* @param {array} [options.documents=[]] Initial documents list for cursor
|
|
73
73
|
* @param {object} [options.transforms=null] Transform methods for the cursor results
|
|
74
74
|
* @param {function} [options.transforms.query] Transform the value returned from the initial query
|