mongodb 2.2.27 → 2.2.31

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 CHANGED
@@ -1,3 +1,43 @@
1
+ 2.2.31 2017-08-08
2
+ -----------------
3
+ * update mongodb-core to 2.2.15
4
+ * allow auth option in MongoClient.connect
5
+ * remove duplicate option `promoteLongs` from MongoClient's `connect`
6
+ * bulk operations should not throw an error on empty batch
7
+
8
+ 2.2.30 2017-07-07
9
+ -----------------
10
+ * Update mongodb-core to 2.2.14
11
+ * MongoClient
12
+ * add `appname` to list of valid option names
13
+ * added test for passing appname as option
14
+ * NODE-1052 ensure user options are applied while parsing connection string uris
15
+
16
+ 2.2.29 2017-06-19
17
+ -----------------
18
+ * Update mongodb-core to 2.1.13
19
+ * NODE-1039 ensure we force destroy server instances, forcing queue to be flushed.
20
+ * Use actual server type in standalone SDAM events.
21
+ * Allow multiple map calls (Issue #1521, https://github.com/Robbilie).
22
+ * Clone insertMany options before mutating (Issue #1522, https://github.com/vkarpov15).
23
+ * NODE-1034 Fix GridStore issue caused by Node 8.0.0 breaking backward compatible fs.read API.
24
+ * NODE-1026, use operator instead of skip function in order to avoid useless fetch stage.
25
+
26
+ 2.2.28 2017-06-02
27
+ -----------------
28
+ * Update mongodb-core to 2.1.12
29
+ * NODE-1019 Set keepAlive to 300 seconds or 1/2 of socketTimeout if socketTimeout < keepAlive.
30
+ * Minor fix to report the correct state on error.
31
+ * NODE-1020 'family' was added to options to provide high priority for ipv6 addresses (Issue #1518, https://github.com/firej).
32
+ * Fix require_optional loading of bson-ext.
33
+ * Ensure no errors are thrown by replset if topology is destroyed before it finished connecting.
34
+ * NODE-999 SDAM fixes for Mongos and single Server event emitting.
35
+ * NODE-1014 Set socketTimeout to default to 360 seconds.
36
+ * NODE-1019 Set keepAlive to 300 seconds or 1/2 of socketTimeout if socketTimeout < keepAlive.
37
+ * Just handle Collection name errors distinctly from general callback errors avoiding double callbacks in Db.collection.
38
+ * NODE-999 SDAM fixes for Mongos and single Server event emitting.
39
+ * NODE-1000 Added guard condition for upload.js checkDone function in case of race condition caused by late arriving chunk write.
40
+
1
41
  2.2.27 2017-05-22
2
42
  -----------------
3
43
  * Updated mongodb-core to 2.1.11
@@ -488,30 +488,37 @@ var executeCommands = function(self, callback) {
488
488
  */
489
489
  OrderedBulkOperation.prototype.execute = function(_writeConcern, callback) {
490
490
  var self = this;
491
- if(this.s.executed) throw new toError("batch cannot be re-executed");
492
- if(typeof _writeConcern == 'function') {
491
+ if (this.s.executed) {
492
+ var executedError = toError('batch cannot be re-executed');
493
+ return (typeof callback === 'function') ?
494
+ callback(executedError, null) : this.s.promiseLibrary.reject(executedError);
495
+ }
496
+
497
+ if (typeof _writeConcern === 'function') {
493
498
  callback = _writeConcern;
494
- } else if(_writeConcern && typeof _writeConcern == 'object') {
499
+ } else if (_writeConcern && typeof _writeConcern === 'object') {
495
500
  this.s.writeConcern = _writeConcern;
496
501
  }
497
502
 
498
503
  // If we have current batch
499
- if(this.s.currentBatch) this.s.batches.push(this.s.currentBatch)
504
+ if (this.s.currentBatch) this.s.batches.push(this.s.currentBatch)
500
505
 
501
506
  // If we have no operations in the bulk raise an error
502
- if(this.s.batches.length == 0) {
503
- throw toError("Invalid Operation, No operations in bulk");
507
+ if (this.s.batches.length == 0) {
508
+ var emptyBatchError = toError('Invalid Operation, no operations specified');
509
+ return (typeof callback === 'function') ?
510
+ callback(emptyBatchError, null) : this.s.promiseLibrary.reject(emptyBatchError);
504
511
  }
505
512
 
506
513
  // Execute using callback
507
- if(typeof callback == 'function') {
508
- return executeCommands(this, callback);
509
- }
514
+ if (typeof callback === 'function') {
515
+ return executeCommands(this, callback);
516
+ }
510
517
 
511
518
  // Return a Promise
512
519
  return new this.s.promiseLibrary(function(resolve, reject) {
513
520
  executeCommands(self, function(err, r) {
514
- if(err) return reject(err);
521
+ if (err) return reject(err);
515
522
  resolve(r);
516
523
  });
517
524
  });
@@ -490,30 +490,37 @@ var executeBatches = function(self, callback) {
490
490
  */
491
491
  UnorderedBulkOperation.prototype.execute = function(_writeConcern, callback) {
492
492
  var self = this;
493
- if(this.s.executed) throw toError("batch cannot be re-executed");
494
- if(typeof _writeConcern == 'function') {
493
+ if (this.s.executed) {
494
+ var executedError = toError('batch cannot be re-executed');
495
+ return (typeof callback === 'function') ?
496
+ callback(executedError, null) : this.s.promiseLibrary.reject(executedError);
497
+ }
498
+
499
+ if (typeof _writeConcern === 'function') {
495
500
  callback = _writeConcern;
496
- } else if(_writeConcern && typeof _writeConcern == 'object') {
501
+ } else if (_writeConcern && typeof _writeConcern === 'object') {
497
502
  this.s.writeConcern = _writeConcern;
498
503
  }
499
504
 
500
505
  // If we have current batch
501
- if(this.s.currentInsertBatch) this.s.batches.push(this.s.currentInsertBatch);
502
- if(this.s.currentUpdateBatch) this.s.batches.push(this.s.currentUpdateBatch);
503
- if(this.s.currentRemoveBatch) this.s.batches.push(this.s.currentRemoveBatch);
506
+ if (this.s.currentInsertBatch) this.s.batches.push(this.s.currentInsertBatch);
507
+ if (this.s.currentUpdateBatch) this.s.batches.push(this.s.currentUpdateBatch);
508
+ if (this.s.currentRemoveBatch) this.s.batches.push(this.s.currentRemoveBatch);
504
509
 
505
510
  // If we have no operations in the bulk raise an error
506
- if(this.s.batches.length == 0) {
507
- throw toError("Invalid Operation, No operations in bulk");
511
+ if (this.s.batches.length == 0) {
512
+ var emptyBatchError = toError('Invalid Operation, no operations specified');
513
+ return (typeof callback === 'function') ?
514
+ callback(emptyBatchError, null) : this.s.promiseLibrary.reject(emptyBatchError);
508
515
  }
509
516
 
510
517
  // Execute using callback
511
- if(typeof callback == 'function') return executeBatches(this, callback);
518
+ if (typeof callback === 'function') return executeBatches(this, callback);
512
519
 
513
520
  // Return a Promise
514
521
  return new this.s.promiseLibrary(function(resolve, reject) {
515
522
  executeBatches(self, function(err, r) {
516
- if(err) return reject(err);
523
+ if (err) return reject(err);
517
524
  resolve(r);
518
525
  });
519
526
  });
package/lib/collection.js CHANGED
@@ -496,7 +496,7 @@ define.classMethod('insertOne', {callback: true, promise:true});
496
496
  Collection.prototype.insertMany = function(docs, options, callback) {
497
497
  var self = this;
498
498
  if(typeof options == 'function') callback = options, options = {};
499
- options = options || {ordered:true};
499
+ options = options ? shallowClone(options) : {ordered:true};
500
500
  if(!Array.isArray(docs) && typeof callback == 'function') {
501
501
  return callback(MongoError.create({message: 'docs parameter must be an array of documents', driver:true }));
502
502
  } else if(!Array.isArray(docs)) {
package/lib/cursor.js CHANGED
@@ -1003,7 +1003,12 @@ define.classMethod('close', {callback: true, promise:true});
1003
1003
  * @return {Cursor}
1004
1004
  */
1005
1005
  Cursor.prototype.map = function(transform) {
1006
- this.cursorState.transforms = { doc: transform };
1006
+ if(this.cursorState.transforms && this.cursorState.transforms.doc) {
1007
+ var oldTransform = this.cursorState.transforms.doc;
1008
+ this.cursorState.transforms.doc = function (doc) { return transform(oldTransform(doc)); };
1009
+ } else {
1010
+ this.cursorState.transforms = { doc: transform };
1011
+ }
1007
1012
  return this;
1008
1013
  }
1009
1014
 
package/lib/db.js CHANGED
@@ -462,6 +462,7 @@ Db.prototype.collection = function(name, options, callback) {
462
462
  if(callback) callback(null, collection);
463
463
  return collection;
464
464
  } catch(err) {
465
+ // if(err instanceof MongoError && callback) return callback(err);
465
466
  if(callback) return callback(err);
466
467
  throw err;
467
468
  }
@@ -1482,7 +1483,7 @@ Db.prototype.removeUser = function(username, options, callback) {
1482
1483
  * @deprecated This method will no longer be available in the next major release 3.x as MongoDB 3.6 will only allow auth against users in the admin db and will no longer allow multiple credentials on a socket. Please authenticate using MongoClient.connect with auth credentials.
1483
1484
  */
1484
1485
  Db.prototype.authenticate = function(username, password, options, callback) {
1485
- console.warn("Db.prototype.authenticate method will no longer be available in the next major release 3.x as MongoDB 3.6 will only allow auth against users in the admin db and will no longer allow multiple credentials on a socket. Please authenticate using MongoClient.connect with auth credentials.");
1486
+ console.warn("Db.prototype.authenticate method will no longer be available in the next major release 3.x as MongoDB 3.6 will only allow auth against users in the admin db and will no longer allow multiple credentials on a socket. Please authenticate using MongoClient.connect with auth credentials.");
1486
1487
  return authenticate.apply(this, [this].concat(Array.prototype.slice.call(arguments)));
1487
1488
  };
1488
1489
 
@@ -427,20 +427,23 @@ var writeFile = function(self, file, callback) {
427
427
 
428
428
  // Write a chunk
429
429
  var writeChunk = function() {
430
- fs.read(file, self.chunkSize, offset, 'binary', function(err, data, bytesRead) {
430
+ // Allocate the buffer
431
+ var _buffer = new Buffer(self.chunkSize);
432
+ // Read the file
433
+ fs.read(file, _buffer, 0, _buffer.length, offset, function(err, bytesRead, data) {
431
434
  if(err) return callback(err, self);
432
435
 
433
436
  offset = offset + bytesRead;
434
437
 
435
438
  // Create a new chunk for the data
436
439
  var chunk = new Chunk(self, {n:index++}, self.writeConcern);
437
- chunk.write(data, function(err, chunk) {
440
+ chunk.write(data.slice(0, bytesRead), function(err, chunk) {
438
441
  if(err) return callback(err, self);
439
442
 
440
443
  chunk.save({}, function(err) {
441
444
  if(err) return callback(err, self);
442
445
 
443
- self.position = self.position + data.length;
446
+ self.position = self.position + bytesRead;
444
447
 
445
448
  // Point to current chunk
446
449
  self.currentChunk = chunk;
@@ -298,15 +298,27 @@ function init(self) {
298
298
  return;
299
299
  }
300
300
 
301
- self.s.cursor = self.s.chunks.find({ files_id: doc._id }).sort({ n: 1 });
301
+ self.s.bytesToSkip = handleStartOption(self, doc, self.s.options);
302
+
303
+ var filter = { files_id: doc._id };
304
+
305
+ // Currently (MongoDB 3.4.4) skip function does not support the index,
306
+ // it needs to retrieve all the documents first and then skip them. (CS-25811)
307
+ // As work around we use $gte on the "n" field.
308
+ if (self.s.options && self.s.options.start != null){
309
+ var skip = Math.floor(self.s.options.start / doc.chunkSize);
310
+ if (skip > 0){
311
+ filter["n"] = {"$gte": skip};
312
+ }
313
+ }
314
+ self.s.cursor = self.s.chunks.find(filter).sort({ n: 1 });
315
+
302
316
  if (self.s.readPreference) {
303
317
  self.s.cursor.setReadPreference(self.s.readPreference);
304
318
  }
305
319
 
306
320
  self.s.expectedEnd = Math.ceil(doc.length / doc.chunkSize);
307
321
  self.s.file = doc;
308
- self.s.bytesToSkip = handleStartOption(self, doc, self.s.cursor,
309
- self.s.options);
310
322
  self.s.bytesToTrim = handleEndOption(self, doc, self.s.cursor,
311
323
  self.s.options);
312
324
  self.emit('file', doc);
@@ -336,11 +348,11 @@ function waitForFile(_this, callback) {
336
348
  * @ignore
337
349
  */
338
350
 
339
- function handleStartOption(stream, doc, cursor, options) {
351
+ function handleStartOption(stream, doc, options) {
340
352
  if (options && options.start != null) {
341
353
  if (options.start > doc.length) {
342
354
  throw new Error('Stream start (' + options.start + ') must not be ' +
343
- 'more than the length of the file (' + doc.length +')')
355
+ 'more than the length of the file (' + doc.length +')');
344
356
  }
345
357
  if (options.start < 0) {
346
358
  throw new Error('Stream start (' + options.start + ') must not be ' +
@@ -351,8 +363,6 @@ function handleStartOption(stream, doc, cursor, options) {
351
363
  'greater than stream end (' + options.end + ')');
352
364
  }
353
365
 
354
- cursor.skip(Math.floor(options.start / doc.chunkSize));
355
-
356
366
  stream.s.bytesRead = Math.floor(options.start / doc.chunkSize) *
357
367
  doc.chunkSize;
358
368
  stream.s.expected = Math.floor(options.start / doc.chunkSize);
@@ -33,6 +33,8 @@ function GridFSBucketWriteStream(bucket, filename, options) {
33
33
  this.filename = filename;
34
34
  this.files = bucket.s._filesCollection;
35
35
  this.options = options;
36
+ // Signals the write is all done
37
+ this.done = false;
36
38
 
37
39
  this.id = options.id ? options.id : core.BSON.ObjectId();
38
40
  this.chunkSizeBytes = this.options.chunkSizeBytes;
@@ -252,9 +254,13 @@ function checkChunksIndex(_this, callback) {
252
254
  */
253
255
 
254
256
  function checkDone(_this, callback) {
257
+ if(_this.done) return true;
255
258
  if (_this.state.streamEnd &&
256
259
  _this.state.outstandingRequests === 0 &&
257
260
  !_this.state.errored) {
261
+ // Set done so we dont' trigger duplicate createFilesDoc
262
+ _this.done = true;
263
+ // Create a new files doc
258
264
  var filesDoc = createFilesDoc(_this.id, _this.length, _this.chunkSizeBytes,
259
265
  _this.md5.digest('hex'), _this.filename, _this.options.contentType,
260
266
  _this.options.aliases, _this.options.metadata);
@@ -421,6 +427,7 @@ function doWrite(_this, chunk, encoding, callback) {
421
427
  }
422
428
  --_this.state.outstandingRequests;
423
429
  --outstandingRequests;
430
+
424
431
  if (!outstandingRequests) {
425
432
  _this.emit('drain', doc);
426
433
  callback && callback();
@@ -12,6 +12,7 @@ var parse = require('./url_parser')
12
12
  , MongoError = require('mongodb-core').MongoError
13
13
  , Db = require('./db')
14
14
  , f = require('util').format
15
+ , assign = require('./utils').assign
15
16
  , shallowClone = require('./utils').shallowClone
16
17
  , authenticate = require('./authenticate');
17
18
 
@@ -30,14 +31,14 @@ var parse = require('./url_parser')
30
31
  * });
31
32
  */
32
33
  var validOptionNames = ['poolSize', 'ssl', 'sslValidate', 'sslCA', 'sslCert',
33
- 'sslKey', 'sslPass', 'sslCRL', 'autoReconnect', 'noDelay', 'keepAlive', 'connectTimeoutMS',
34
+ 'sslKey', 'sslPass', 'sslCRL', 'autoReconnect', 'noDelay', 'keepAlive', 'connectTimeoutMS', 'family',
34
35
  'socketTimeoutMS', 'reconnectTries', 'reconnectInterval', 'ha', 'haInterval',
35
36
  'replicaSet', 'secondaryAcceptableLatencyMS', 'acceptableLatencyMS',
36
37
  'connectWithNoPrimary', 'authSource', 'w', 'wtimeout', 'j', 'forceServerObjectId',
37
- 'serializeFunctions', 'ignoreUndefined', 'raw', 'promoteLongs', 'bufferMaxEntries',
38
+ 'serializeFunctions', 'ignoreUndefined', 'raw', 'bufferMaxEntries',
38
39
  'readPreference', 'pkFactory', 'promiseLibrary', 'readConcern', 'maxStalenessSeconds',
39
40
  'loggerLevel', 'logger', 'promoteValues', 'promoteBuffers', 'promoteLongs',
40
- 'domainsEnabled', 'keepAliveInitialDelay', 'checkServerIdentity', 'validateOptions'];
41
+ 'domainsEnabled', 'keepAliveInitialDelay', 'checkServerIdentity', 'validateOptions', 'appname', 'auth'];
41
42
  var ignoreOptionNames = ['native_parser'];
42
43
  var legacyOptionNames = ['server', 'replset', 'replSet', 'mongos', 'db'];
43
44
 
@@ -100,9 +101,10 @@ function MongoClient() {
100
101
  * @param {boolean|function} [options.checkServerIdentity=true] Ensure we check server identify during SSL, set to false to disable checking. Only works for Node 0.12.x or higher. You can pass in a boolean or your own checkServerIdentity override function.
101
102
  * @param {boolean} [options.autoReconnect=true] Enable autoReconnect for single server instances
102
103
  * @param {boolean} [options.noDelay=true] TCP Connection no delay
103
- * @param {boolean} [options.keepAlive=0] The number of milliseconds to wait before initiating keepAlive on the TCP socket.
104
+ * @param {number} [options.family=4] Version of IP stack. Defaults to 4.
105
+ * @param {boolean} [options.keepAlive=30000] The number of milliseconds to wait before initiating keepAlive on the TCP socket.
104
106
  * @param {number} [options.connectTimeoutMS=30000] TCP Connection timeout setting
105
- * @param {number} [options.socketTimeoutMS=30000] TCP Socket timeout setting
107
+ * @param {number} [options.socketTimeoutMS=360000] TCP Socket timeout setting
106
108
  * @param {number} [options.reconnectTries=30] Server attempt to reconnect #times
107
109
  * @param {number} [options.reconnectInterval=1000] Server will wait # milliseconds between retries
108
110
  * @param {boolean} [options.ha=true] Control if high availability monitoring runs for Replicaset or Mongos proxies.
@@ -112,6 +114,8 @@ function MongoClient() {
112
114
  * @param {number} [options.acceptableLatencyMS=15] Cutoff latency point in MS for Mongos proxies selection.
113
115
  * @param {boolean} [options.connectWithNoPrimary=false] Sets if the driver should connect even if no primary is available
114
116
  * @param {string} [options.authSource=undefined] Define the database to authenticate against
117
+ * @param {string} [options.auth.user=undefined] The username for auth
118
+ * @param {string} [options.auth.password=undefined] The username for auth
115
119
  * @param {(number|string)} [options.w=null] The write concern.
116
120
  * @param {number} [options.wtimeout=null] The write concern timeout.
117
121
  * @param {boolean} [options.j=false] Specify a journal write concern.
@@ -130,6 +134,7 @@ function MongoClient() {
130
134
  * @param {object} [options.readConcern=null] Specify a read concern for the collection. (only MongoDB 3.2 or higher supported)
131
135
  * @param {string} [options.readConcern.level='local'] Specify a read concern level for the collection operations, one of [local|majority]. (only MongoDB 3.2 or higher supported)
132
136
  * @param {number} [options.maxStalenessSeconds=undefined] The max staleness to secondary reads (values under 10 seconds cannot be guaranteed);
137
+ * @param {string} [options.appname=undefined] The name of the application that created this MongoClient instance. MongoDB 3.4 and newer will print this value in the server log upon establishing each connection. It is also recorded in the slow query log and profile collections.
133
138
  * @param {string} [options.loggerLevel=undefined] The logging level (error/warn/info/debug)
134
139
  * @param {object} [options.logger=undefined] Custom logger object
135
140
  * @param {object} [options.validateOptions=false] Validate MongoClient passed in options for correctness.
@@ -167,9 +172,10 @@ var define = MongoClient.define = new Define('MongoClient', MongoClient, false);
167
172
  * @param {boolean|function} [options.checkServerIdentity=true] Ensure we check server identify during SSL, set to false to disable checking. Only works for Node 0.12.x or higher. You can pass in a boolean or your own checkServerIdentity override function.
168
173
  * @param {boolean} [options.autoReconnect=true] Enable autoReconnect for single server instances
169
174
  * @param {boolean} [options.noDelay=true] TCP Connection no delay
170
- * @param {boolean} [options.keepAlive=0] The number of milliseconds to wait before initiating keepAlive on the TCP socket.
175
+ * @param {number} [options.family=4] Version of IP stack. Defaults to 4.
176
+ * @param {boolean} [options.keepAlive=30000] The number of milliseconds to wait before initiating keepAlive on the TCP socket.
171
177
  * @param {number} [options.connectTimeoutMS=30000] TCP Connection timeout setting
172
- * @param {number} [options.socketTimeoutMS=30000] TCP Socket timeout setting
178
+ * @param {number} [options.socketTimeoutMS=360000] TCP Socket timeout setting
173
179
  * @param {number} [options.reconnectTries=30] Server attempt to reconnect #times
174
180
  * @param {number} [options.reconnectInterval=1000] Server will wait # milliseconds between retries
175
181
  * @param {boolean} [options.ha=true] Control if high availability monitoring runs for Replicaset or Mongos proxies.
@@ -179,6 +185,8 @@ var define = MongoClient.define = new Define('MongoClient', MongoClient, false);
179
185
  * @param {number} [options.acceptableLatencyMS=15] Cutoff latency point in MS for Mongos proxies selection.
180
186
  * @param {boolean} [options.connectWithNoPrimary=false] Sets if the driver should connect even if no primary is available
181
187
  * @param {string} [options.authSource=undefined] Define the database to authenticate against
188
+ * @param {string} [options.auth.user=undefined] The username for auth
189
+ * @param {string} [options.auth.password=undefined] The username for auth
182
190
  * @param {(number|string)} [options.w=null] The write concern.
183
191
  * @param {number} [options.wtimeout=null] The write concern timeout.
184
192
  * @param {boolean} [options.j=false] Specify a journal write concern.
@@ -197,6 +205,7 @@ var define = MongoClient.define = new Define('MongoClient', MongoClient, false);
197
205
  * @param {object} [options.readConcern=null] Specify a read concern for the collection. (only MongoDB 3.2 or higher supported)
198
206
  * @param {string} [options.readConcern.level='local'] Specify a read concern level for the collection operations, one of [local|majority]. (only MongoDB 3.2 or higher supported)
199
207
  * @param {number} [options.maxStalenessSeconds=undefined] The max staleness to secondary reads (values under 10 seconds cannot be guaranteed);
208
+ * @param {string} [options.appname=undefined] The name of the application that created this MongoClient instance. MongoDB 3.4 and newer will print this value in the server log upon establishing each connection. It is also recorded in the slow query log and profile collections.
200
209
  * @param {string} [options.loggerLevel=undefined] The logging level (error/warn/info/debug)
201
210
  * @param {object} [options.logger=undefined] Custom logger object
202
211
  * @param {object} [options.validateOptions=false] Validate MongoClient passed in options for correctness.
@@ -294,7 +303,7 @@ function translateOptions(options) {
294
303
  }
295
304
 
296
305
  // Set the socket and connection timeouts
297
- if(options.socketTimeoutMS == null) options.socketTimeoutMS = 30000;
306
+ if(options.socketTimeoutMS == null) options.socketTimeoutMS = 360000;
298
307
  if(options.connectTimeoutMS == null) options.connectTimeoutMS = 30000;
299
308
 
300
309
  // Create server instances
@@ -305,6 +314,37 @@ function translateOptions(options) {
305
314
  });
306
315
  }
307
316
 
317
+ //
318
+ // Collect all events in order from SDAM
319
+ //
320
+ function collectEvents(self, db) {
321
+ var collectedEvents = [];
322
+
323
+ if(self instanceof MongoClient) {
324
+ var events = ["timeout", "close", 'serverOpening', 'serverDescriptionChanged', 'serverHeartbeatStarted',
325
+ 'serverHeartbeatSucceeded', 'serverHeartbeatFailed', 'serverClosed', 'topologyOpening',
326
+ 'topologyClosed', 'topologyDescriptionChanged', 'joined', 'left', 'ping', 'ha', 'all', 'fullsetup'];
327
+ events.forEach(function(event) {
328
+ db.serverConfig.on(event, function(object1, object2) {
329
+ collectedEvents.push({
330
+ event: event, object1: object1, object2: object2
331
+ });
332
+ });
333
+ });
334
+ }
335
+
336
+ return collectedEvents;
337
+ }
338
+
339
+ //
340
+ // Replay any events due to single server connection switching to Mongos
341
+ //
342
+ function replayEvents(self, events) {
343
+ for(var i = 0; i < events.length; i++) {
344
+ self.emit(events[i].event, events[i].object1, events[i].object2);
345
+ }
346
+ }
347
+
308
348
  function relayEvents(self, db) {
309
349
  if(self instanceof MongoClient) {
310
350
  var events = ["timeout", "close", 'serverOpening', 'serverDescriptionChanged', 'serverHeartbeatStarted',
@@ -325,7 +365,7 @@ function createReplicaset(self, options, callback) {
325
365
  var db = new Db(options.dbName, new ReplSet(servers, options), options);
326
366
  // Propegate the events to the client
327
367
  relayEvents(self, db);
328
- // Open the connection
368
+ // Open the connection
329
369
  db.open(callback);
330
370
  }
331
371
 
@@ -336,7 +376,7 @@ function createMongos(self, options, callback) {
336
376
  var db = new Db(options.dbName, new Mongos(servers, options), options)
337
377
  // Propegate the events to the client
338
378
  relayEvents(self, db);
339
- // Open the connection
379
+ // Open the connection
340
380
  db.open(callback);
341
381
  }
342
382
 
@@ -346,7 +386,7 @@ function createServer(self, options, callback) {
346
386
  // Create db instance
347
387
  var db = new Db(options.dbName, servers[0], options);
348
388
  // Propegate the events to the client
349
- relayEvents(self, db);
389
+ var collectedEvents = collectEvents(self, db);
350
390
  // Create Db instance
351
391
  db.open(function(err, db) {
352
392
  if(err) return callback(err);
@@ -361,6 +401,10 @@ function createServer(self, options, callback) {
361
401
  return createMongos(self, options, callback);
362
402
  }
363
403
 
404
+ // Fire all the events
405
+ replayEvents(self, collectedEvents);
406
+ // Propegate the events to the client
407
+ relayEvents(self, db);
364
408
  // Otherwise callback
365
409
  callback(err, db);
366
410
  });
@@ -445,9 +489,13 @@ var connect = function(self, url, options, callback) {
445
489
  _finalOptions = createUnifiedOptions(_finalOptions, options);
446
490
 
447
491
  // Check if we have connection and socket timeout set
448
- if(_finalOptions.socketTimeoutMS == null) _finalOptions.socketTimeoutMS = 30000;
492
+ if(_finalOptions.socketTimeoutMS == null) _finalOptions.socketTimeoutMS = 360000;
449
493
  if(_finalOptions.connectTimeoutMS == null) _finalOptions.connectTimeoutMS = 30000;
450
494
 
495
+ if (_finalOptions.db_options && _finalOptions.db_options.auth) {
496
+ delete _finalOptions.db_options.auth;
497
+ }
498
+
451
499
  // Failure modes
452
500
  if(object.servers.length == 0) {
453
501
  throw new Error("connection string must contain at least one seed host");
package/lib/mongos.js CHANGED
@@ -283,9 +283,8 @@ Mongos.prototype.connect = function(db, _options, callback) {
283
283
  // Connect handler
284
284
  var connectHandler = function() {
285
285
  // Clear out all the current handlers left over
286
- ["timeout", "error", "close", 'serverOpening', 'serverDescriptionChanged', 'serverHeartbeatStarted',
287
- 'serverHeartbeatSucceeded', 'serverHeartbeatFailed', 'serverClosed', 'topologyOpening',
288
- 'topologyClosed', 'topologyDescriptionChanged'].forEach(function(e) {
286
+ var events = ["timeout", "error", "close", 'fullsetup'];
287
+ events.forEach(function(e) {
289
288
  self.s.mongos.removeAllListeners(e);
290
289
  });
291
290
 
@@ -294,19 +293,8 @@ Mongos.prototype.connect = function(db, _options, callback) {
294
293
  self.s.mongos.once('error', errorHandler('error'));
295
294
  self.s.mongos.once('close', errorHandler('close'));
296
295
 
297
- // Set up SDAM listeners
298
- self.s.mongos.on('serverDescriptionChanged', relay('serverDescriptionChanged'));
299
- self.s.mongos.on('serverHeartbeatStarted', relay('serverHeartbeatStarted'));
300
- self.s.mongos.on('serverHeartbeatSucceeded', relay('serverHeartbeatSucceeded'));
301
- self.s.mongos.on('serverHeartbeatFailed', relay('serverHeartbeatFailed'));
302
- self.s.mongos.on('serverOpening', relay('serverOpening'));
303
- self.s.mongos.on('serverClosed', relay('serverClosed'));
304
- self.s.mongos.on('topologyOpening', relay('topologyOpening'));
305
- self.s.mongos.on('topologyClosed', relay('topologyClosed'));
306
- self.s.mongos.on('topologyDescriptionChanged', relay('topologyDescriptionChanged'));
307
-
308
296
  // Set up serverConfig listeners
309
- self.s.mongos.on('fullsetup', relay('fullsetup'));
297
+ self.s.mongos.on('fullsetup', function() { self.emit('fullsetup', self); });
310
298
 
311
299
  // Emit open event
312
300
  self.emit('open', null, self);
@@ -319,6 +307,25 @@ Mongos.prototype.connect = function(db, _options, callback) {
319
307
  }
320
308
  }
321
309
 
310
+ // Clear out all the current handlers left over
311
+ var events = ["timeout", "error", "close", 'serverOpening', 'serverDescriptionChanged', 'serverHeartbeatStarted',
312
+ 'serverHeartbeatSucceeded', 'serverHeartbeatFailed', 'serverClosed', 'topologyOpening',
313
+ 'topologyClosed', 'topologyDescriptionChanged'];
314
+ events.forEach(function(e) {
315
+ self.s.mongos.removeAllListeners(e);
316
+ });
317
+
318
+ // Set up SDAM listeners
319
+ self.s.mongos.on('serverDescriptionChanged', relay('serverDescriptionChanged'));
320
+ self.s.mongos.on('serverHeartbeatStarted', relay('serverHeartbeatStarted'));
321
+ self.s.mongos.on('serverHeartbeatSucceeded', relay('serverHeartbeatSucceeded'));
322
+ self.s.mongos.on('serverHeartbeatFailed', relay('serverHeartbeatFailed'));
323
+ self.s.mongos.on('serverOpening', relay('serverOpening'));
324
+ self.s.mongos.on('serverClosed', relay('serverClosed'));
325
+ self.s.mongos.on('topologyOpening', relay('topologyOpening'));
326
+ self.s.mongos.on('topologyClosed', relay('topologyClosed'));
327
+ self.s.mongos.on('topologyDescriptionChanged', relay('topologyDescriptionChanged'));
328
+
322
329
  // Set up listeners
323
330
  self.s.mongos.once('timeout', connectErrorHandler('timeout'));
324
331
  self.s.mongos.once('error', connectErrorHandler('error'));
package/lib/replset.js CHANGED
@@ -44,7 +44,7 @@ var legalOptionNames = ['ha', 'haInterval', 'replicaSet', 'rs_name', 'secondaryA
44
44
  , 'connectWithNoPrimary', 'poolSize', 'ssl', 'checkServerIdentity', 'sslValidate'
45
45
  , 'sslCA', 'sslCert', 'sslCRL', 'sslKey', 'sslPass', 'socketOptions', 'bufferMaxEntries'
46
46
  , 'store', 'auto_reconnect', 'autoReconnect', 'emitError'
47
- , 'keepAlive', 'noDelay', 'connectTimeoutMS', 'socketTimeoutMS', 'strategy', 'debug'
47
+ , 'keepAlive', 'noDelay', 'connectTimeoutMS', 'socketTimeoutMS', 'strategy', 'debug', 'family'
48
48
  , 'loggerLevel', 'logger', 'reconnectTries', 'appname', 'domainsEnabled'
49
49
  , 'servername', 'promoteLongs', 'promoteValues', 'promoteBuffers', 'maxStalenessSeconds'];
50
50
 
@@ -62,7 +62,7 @@ var release = os.release();
62
62
  * @deprecated
63
63
  * @param {Server[]} servers A seedlist of servers participating in the replicaset.
64
64
  * @param {object} [options=null] Optional settings.
65
- * @param {booelan} [options.ha=true] Turn on high availability monitoring.
65
+ * @param {boolean} [options.ha=true] Turn on high availability monitoring.
66
66
  * @param {number} [options.haInterval=10000] Time between each replicaset status check.
67
67
  * @param {string} [options.replicaSet] The name of the replicaset to connect to.
68
68
  * @param {number} [options.secondaryAcceptableLatencyMS=15] Sets the range of servers to pick when using NEAREST (lowest ping ms + the latency fence, ex: range of 1 to (1 + 15) ms)
@@ -321,7 +321,7 @@ ReplSet.prototype.connect = function(db, _options, callback) {
321
321
  self.s.replset.on('topologyDescriptionChanged', relay('topologyDescriptionChanged'));
322
322
 
323
323
  self.s.replset.on('fullsetup', function() {
324
- self.emit('fullsetup', null, self);
324
+ self.emit('fullsetup', self, self);
325
325
  });
326
326
 
327
327
  self.s.replset.on('all', function() {
@@ -335,31 +335,6 @@ ReplSet.prototype.connect = function(db, _options, callback) {
335
335
  self.s.replset.once('error', errorHandler('error'));
336
336
  self.s.replset.once('close', errorHandler('close'));
337
337
 
338
- // // Set up serverConfig listeners
339
- // self.s.replset.on('joined', replsetRelay('joined'));
340
- // self.s.replset.on('left', relay('left'));
341
- // self.s.replset.on('ping', relay('ping'));
342
- // self.s.replset.on('ha', relayHa);
343
-
344
- // // Set up SDAM listeners
345
- // self.s.replset.on('serverDescriptionChanged', relay('serverDescriptionChanged'));
346
- // self.s.replset.on('serverHeartbeatStarted', relay('serverHeartbeatStarted'));
347
- // self.s.replset.on('serverHeartbeatSucceeded', relay('serverHeartbeatSucceeded'));
348
- // self.s.replset.on('serverHeartbeatFailed', relay('serverHeartbeatFailed'));
349
- // self.s.replset.on('serverOpening', relay('serverOpening'));
350
- // self.s.replset.on('serverClosed', relay('serverClosed'));
351
- // self.s.replset.on('topologyOpening', relay('topologyOpening'));
352
- // self.s.replset.on('topologyClosed', relay('topologyClosed'));
353
- // self.s.replset.on('topologyDescriptionChanged', relay('topologyDescriptionChanged'));
354
-
355
- // self.s.replset.on('fullsetup', function() {
356
- // self.emit('fullsetup', null, self);
357
- // });
358
-
359
- // self.s.replset.on('all', function() {
360
- // self.emit('all', null, self);
361
- // });
362
-
363
338
  // Emit open event
364
339
  self.emit('open', null, self);
365
340