aboutsummaryrefslogtreecommitdiff
path: root/node_modules/mongodb/lib
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/mongodb/lib')
-rw-r--r--node_modules/mongodb/lib/aggregation_cursor.js3
-rw-r--r--node_modules/mongodb/lib/bulk/ordered.js2
-rw-r--r--node_modules/mongodb/lib/collection.js146
-rw-r--r--node_modules/mongodb/lib/command_cursor.js2
-rw-r--r--node_modules/mongodb/lib/cursor.js18
-rw-r--r--node_modules/mongodb/lib/db.js72
-rw-r--r--node_modules/mongodb/lib/mongo_client.js41
-rw-r--r--node_modules/mongodb/lib/mongos.js36
-rw-r--r--node_modules/mongodb/lib/read_preference.js50
-rw-r--r--node_modules/mongodb/lib/replset.js48
-rw-r--r--node_modules/mongodb/lib/server.js37
-rw-r--r--node_modules/mongodb/lib/topology_base.js9
-rw-r--r--node_modules/mongodb/lib/url_parser.js5
13 files changed, 390 insertions, 79 deletions
diff --git a/node_modules/mongodb/lib/aggregation_cursor.js b/node_modules/mongodb/lib/aggregation_cursor.js
index 3a506c2..7546ee3 100644
--- a/node_modules/mongodb/lib/aggregation_cursor.js
+++ b/node_modules/mongodb/lib/aggregation_cursor.js
@@ -13,8 +13,7 @@ var inherits = require('util').inherits
, Readable = require('stream').Readable || require('readable-stream').Readable
, Define = require('./metadata')
, CoreCursor = require('./cursor')
- , Query = require('mongodb-core').Query
- , CoreReadPreference = require('mongodb-core').ReadPreference;
+ , Query = require('mongodb-core').Query;
/**
* @fileOverview The **AggregationCursor** class is an internal class that embodies an aggregation cursor on MongoDB
diff --git a/node_modules/mongodb/lib/bulk/ordered.js b/node_modules/mongodb/lib/bulk/ordered.js
index a910689..762e861 100644
--- a/node_modules/mongodb/lib/bulk/ordered.js
+++ b/node_modules/mongodb/lib/bulk/ordered.js
@@ -318,6 +318,7 @@ OrderedBulkOperation.prototype.raw = function(op) {
var multi = op.updateOne || op.replaceOne ? false : true;
var operation = {q: op[key].filter, u: op[key].update || op[key].replacement, multi: multi}
operation.upsert = op[key].upsert ? true: false;
+ if(op.collation) operation.collation = op.collation;
return addToOperationsList(this, common.UPDATE, operation);
}
@@ -331,6 +332,7 @@ OrderedBulkOperation.prototype.raw = function(op) {
if(op.deleteOne || op.deleteMany) {
var limit = op.deleteOne ? 1 : 0;
var operation = {q: op[key].filter, limit: limit}
+ if(op.collation) operation.collation = op.collation;
return addToOperationsList(this, common.REMOVE, operation);
}
diff --git a/node_modules/mongodb/lib/collection.js b/node_modules/mongodb/lib/collection.js
index bbe1e3b..5a94403 100644
--- a/node_modules/mongodb/lib/collection.js
+++ b/node_modules/mongodb/lib/collection.js
@@ -122,6 +122,8 @@ var Collection = function(db, topology, dbName, name, pkFactory, options) {
, promiseLibrary: promiseLibrary
// Read Concern
, readConcern: options.readConcern
+ // Collation
+ , collation: options.collation
}
}
@@ -280,6 +282,7 @@ Collection.prototype.find = function() {
// Add read preference if needed
newOptions = getReadPreference(this, newOptions, this.s.db, this);
+
// Set slave ok to true if read preference different from primary
if(newOptions.readPreference != null
&& (newOptions.readPreference != 'primary' || newOptions.readPreference.mode != 'primary')) {
@@ -351,6 +354,9 @@ Collection.prototype.find = function() {
findCommand.readConcern = this.s.readConcern;
}
+ // Decorate find command with collation options
+ decorateWithCollation(findCommand, this, options);
+
// Create the cursor
if(typeof callback == 'function') return handleCallback(callback, null, this.s.topology.cursor(this.s.namespace, findCommand, newOptions));
return this.s.topology.cursor(this.s.namespace, findCommand, newOptions);
@@ -507,9 +513,7 @@ Collection.prototype.insertMany = function(docs, options, callback) {
// Return a Promise
return new this.s.promiseLibrary(function(resolve, reject) {
- // console.log("########## insertMany 0")
bulkWrite(self, operations, options, function(err, r) {
- // console.log("########## insertMany 1")
if(err) return reject(err);
resolve(mapInserManyResults(docs, r));
});
@@ -601,9 +605,25 @@ var bulkWrite = function(self, operations, options, callback) {
// Create the bulk operation
var bulk = options.ordered == true || options.ordered == null ? self.initializeOrderedBulkOp(options) : self.initializeUnorderedBulkOp(options);
+ // Do we have a collation
+ var collation = false;
+
// for each op go through and add to the bulk
try {
for(var i = 0; i < operations.length; i++) {
+ // Get the operation type
+ var key = Object.keys(operations[i])[0];
+ // Check if we have a collation
+ if(operations[i][key].collation) {
+ collation = true;
+ }
+
+ // // Have we specified collation, apply it
+ // decorateWithCollation(operations[i], self, options);
+ // console.log("================ bulkWrite")
+ // console.dir(operations[i])
+
+ // Pass to the raw bulk
bulk.raw(operations[i]);
}
} catch(err) {
@@ -613,6 +633,12 @@ var bulkWrite = function(self, operations, options, callback) {
// Final options for write concern
var finalOptions = writeConcern(shallowClone(options), self.s.db, self, options);
var writeCon = finalOptions.writeConcern ? finalOptions.writeConcern : {};
+ var capabilities = self.s.topology.capabilities();
+
+ // Did the user pass in a collation, check if our write server supports it
+ if(collation && capabilities && !capabilities.commandsTakeCollation) {
+ return callback(new MongoError(f('server/primary/mongos does not support collation')));
+ }
// Execute the bulk
bulk.execute(writeCon, function(err, r) {
@@ -623,11 +649,6 @@ var bulkWrite = function(self, operations, options, callback) {
return callback(toError(r.getWriteErrorAt(0)), r);
}
- // console.log("!!!!!! BULK EXECUTE FINISHED")
- // console.dir(err)
- // console.dir(r)
-
- // if(err) return callback(err);
r.insertedCount = r.nInserted;
r.matchedCount = r.nMatched;
r.modifiedCount = r.nModified || 0;
@@ -1006,6 +1027,9 @@ var updateDocuments = function(self, selector, document, options, callback) {
op.upsert = typeof options.upsert == 'boolean' ? options.upsert : false;
op.multi = typeof options.multi == 'boolean' ? options.multi : false;
+ // Have we specified collation
+ decorateWithCollation(finalOptions, self, options);
+
// Update options
self.s.topology.update(self.s.namespace, [op], finalOptions, function(err, result) {
if(callback == null) return;
@@ -1161,6 +1185,7 @@ Collection.prototype.deleteMany = function(filter, options, callback) {
var deleteMany = function(self, filter, options, callback) {
options.single = false;
+
removeDocuments(self, filter, options, function(err, r) {
if(callback == null) return;
if(err && callback) return callback(err);
@@ -1192,6 +1217,9 @@ var removeDocuments = function(self, selector, options, callback) {
var op = {q: selector, limit: 0};
if(options.single) op.limit = 1;
+ // Have we specified collation
+ decorateWithCollation(finalOptions, self, options);
+
// Execute the remove
self.s.topology.remove(self.s.namespace, [op], finalOptions, function(err, result) {
if(callback == null) return;
@@ -1410,6 +1438,9 @@ var rename = function(self, newName, opt, callback) {
var dropTarget = typeof opt.dropTarget == 'boolean' ? opt.dropTarget : false;
var cmd = {'renameCollection':renameCollection, 'to':toCollection, 'dropTarget':dropTarget};
+ // Decorate command with writeConcern if supported
+ decorateWithWriteConcern(cmd, self, opt);
+
// Execute against admin
self.s.db.admin().command(cmd, opt, function(err, doc) {
if(err) return handleCallback(callback, err, null);
@@ -1436,10 +1467,10 @@ define.classMethod('rename', {callback: true, promise:true});
Collection.prototype.drop = function(options, callback) {
var self = this;
if(typeof options == 'function') callback = options, options = {};
- options = options | {};
+ options = options || {};
// Execute using callback
- if(typeof callback == 'function') return self.s.db.dropCollection(self.s.name, callback);
+ if(typeof callback == 'function') return self.s.db.dropCollection(self.s.name, options, callback);
// Return a Promise
return new this.s.promiseLibrary(function(resolve, reject) {
self.s.db.dropCollection(self.s.name, options, function(err, r) {
@@ -1589,11 +1620,18 @@ Collection.prototype.createIndexes = function(indexSpecs, callback) {
}
var createIndexes = function(self, indexSpecs, callback) {
+ var capabilities = self.s.topology.capabilities();
+
// Ensure we generate the correct name if the parameter is not set
for(var i = 0; i < indexSpecs.length; i++) {
if(indexSpecs[i].name == null) {
var keys = [];
+ // Did the user pass in a collation, check if our write server supports it
+ if(indexSpecs[i].collation && capabilities && !capabilities.commandsTakeCollation) {
+ return callback(new MongoError(f('server/primary/mongos does not support collation')));
+ }
+
for(var name in indexSpecs[i].key) {
keys.push(f('%s_%s', name, indexSpecs[i].key[name]));
}
@@ -1645,7 +1683,10 @@ Collection.prototype.dropIndex = function(indexName, options, callback) {
var dropIndex = function(self, indexName, options, callback) {
// Delete index command
- var cmd = {'deleteIndexes':self.s.name, 'index':indexName};
+ var cmd = {'dropIndexes':self.s.name, 'index':indexName};
+
+ // Decorate command with writeConcern if supported
+ decorateWithWriteConcern(cmd, self, options);
// Execute command
self.s.db.command(cmd, options, function(err, result) {
@@ -1663,11 +1704,15 @@ define.classMethod('dropIndex', {callback: true, promise:true});
* @param {Collection~resultCallback} [callback] The command result callback
* @return {Promise} returns Promise if no callback passed
*/
-Collection.prototype.dropIndexes = function(callback) {
+Collection.prototype.dropIndexes = function(options, callback) {
var self = this;
+ // Do we have options
+ if(typeof options == 'function') callback = options, options = {};
+ options = options || {};
+
// Execute using callback
- if(typeof callback == 'function') return dropIndexes(self, callback);
+ if(typeof callback == 'function') return dropIndexes(self, options, callback);
// Return a Promise
return new this.s.promiseLibrary(function(resolve, reject) {
@@ -1678,8 +1723,8 @@ Collection.prototype.dropIndexes = function(callback) {
});
}
-var dropIndexes = function(self, callback) {
- self.dropIndex('*', function (err, result) {
+var dropIndexes = function(self, options, callback) {
+ self.dropIndex('*', options, function(err, result) {
if(err) return handleCallback(callback, err, false);
handleCallback(callback, null, true);
});
@@ -1726,6 +1771,9 @@ var reIndex = function(self, options, callback) {
// Reindex
var cmd = {'reIndex':self.s.name};
+ // Decorate command with writeConcern if supported
+ decorateWithWriteConcern(cmd, self, options);
+
// Execute the command
self.s.db.command(cmd, options, function(err, result) {
if(callback == null) return;
@@ -1760,25 +1808,20 @@ Collection.prototype.listIndexes = function(options) {
throw new MongoError('cannot connect to server');
}
- // console.log("!!!!!!!!!!!!!! HEY 0")
// We have a list collections command
if(this.s.topology.capabilities().hasListIndexesCommand) {
- // console.log("!!!!!!!!!!!!!! HEY 0:1")
// Cursor options
var cursor = options.batchSize ? {batchSize: options.batchSize} : {}
// Build the command
var command = { listIndexes: this.s.name, cursor: cursor };
- // console.log("!!!!!!!!!!!!!! HEY 0:2")
// Execute the cursor
var cursor = this.s.topology.cursor(f('%s.$cmd', this.s.dbName), command, options);
// Do we have a readPreference, apply it
if(options.readPreference) cursor.setReadPreference(options.readPreference);
- // console.log("!!!!!!!!!!!!!! HEY 0:3")
// Return the cursor
return cursor;
}
- // console.log("!!!!!!!!!!!!!! HEY 1")
// Get the namespace
var ns = f('%s.system.indexes', this.s.dbName);
// Get the query
@@ -1981,6 +2024,9 @@ var count = function(self, query, options, callback) {
cmd.readConcern = self.s.readConcern;
}
+ // Have we specified collation
+ decorateWithCollation(cmd, self, options);
+
// Execute command
self.s.db.command(cmd, options, function(err, result) {
if(err) return handleCallback(callback, err);
@@ -2042,6 +2088,9 @@ var distinct = function(self, key, query, options, callback) {
cmd.readConcern = self.s.readConcern;
}
+ // Have we specified collation
+ decorateWithCollation(cmd, self, options);
+
// Execute the command
self.s.db.command(cmd, options, function(err, result) {
if(err) return handleCallback(callback, err);
@@ -2400,6 +2449,9 @@ var findAndModify = function(self, query, sort, doc, options, callback) {
queryObject.bypassDocumentValidation = finalOptions.bypassDocumentValidation;
}
+ // Have we specified collation
+ decorateWithCollation(queryObject, self, options);
+
// Execute the command
self.s.db.command(queryObject
, options, function(err, result) {
@@ -2452,6 +2504,35 @@ var findAndRemove = function(self, query, sort, options, callback) {
define.classMethod('findAndRemove', {callback: true, promise:true});
+function decorateWithWriteConcern(command, self, options) {
+ // Do we support collation 3.4 and higher
+ var capabilities = self.s.topology.capabilities();
+ // Do we support write concerns 3.4 and higher
+ if(capabilities && capabilities.commandsTakeWriteConcern) {
+ // Get the write concern settings
+ var finalOptions = writeConcern(shallowClone(options), self.s.db, self, options);
+ // Add the write concern to the command
+ if(finalOptions.writeConcern) {
+ command.writeConcern = finalOptions.writeConcern;
+ }
+ }
+}
+
+function decorateWithCollation(command, self, options) {
+ // Do we support collation 3.4 and higher
+ var capabilities = self.s.topology.capabilities();
+ // Do we support write concerns 3.4 and higher
+ if(capabilities && capabilities.commandsTakeCollation) {
+ if(options.collation && typeof options.collation == 'object') {
+ command.collation = options.collation;
+ } else if(self.s.collation && typeof self.s.collation == 'object') {
+ command.collation = self.s.collation;
+ } else if(self.s.db.s.collation && typeof self.s.db.s.collation == 'object') {
+ command.collation = self.s.db.s.collation;
+ }
+ }
+}
+
/**
* Execute an aggregation framework pipeline against the collection, needs MongoDB >= 2.2
* @method
@@ -2469,6 +2550,7 @@ define.classMethod('findAndRemove', {callback: true, promise:true});
*/
Collection.prototype.aggregate = function(pipeline, options, callback) {
var self = this;
+
if(Array.isArray(pipeline)) {
// Set up callback if one is provided
if(typeof options == 'function') {
@@ -2510,6 +2592,11 @@ Collection.prototype.aggregate = function(pipeline, options, callback) {
// Build the command
var command = { aggregate : this.s.name, pipeline : pipeline};
+ // Decorate command with writeConcern if supported
+ decorateWithWriteConcern(command, self, options);
+ // Have we specified collation
+ decorateWithCollation(command, self, options);
+
// If we have bypassDocumentValidation set
if(typeof options.bypassDocumentValidation == 'boolean') {
command.bypassDocumentValidation = options.bypassDocumentValidation;
@@ -2743,6 +2830,9 @@ var geoNear = function(self, x, y, point, options, callback) {
commandObject.readConcern = self.s.readConcern;
}
+ // Have we specified collation
+ decorateWithCollation(commandObject, self, options);
+
// Execute the command
self.s.db.command(commandObject, options, function (err, res) {
if(err) return handleCallback(callback, err);
@@ -2952,6 +3042,9 @@ var group = function(self, keys, condition, initial, reduce, finalize, command,
selector.readConcern = self.s.readConcern;
}
+ // Have we specified collation
+ decorateWithCollation(selector, self, options);
+
// Execute command
self.s.db.command(selector, options, function(err, result) {
if(err) return handleCallback(callback, err, null);
@@ -3085,7 +3178,10 @@ var mapReduce = function(self, map, reduce, options, callback) {
// If we have a read preference and inline is not set as output fail hard
if((options.readPreference != false && options.readPreference != 'primary')
&& options['out'] && (options['out'].inline != 1 && options['out'] != 'inline')) {
+ // Force readPreference to primary
options.readPreference = 'primary';
+ // Decorate command with writeConcern if supported
+ decorateWithWriteConcern(mapCommandHash, self, options);
} else if(self.s.readConcern) {
mapCommandHash.readConcern = self.s.readConcern;
}
@@ -3095,6 +3191,9 @@ var mapReduce = function(self, map, reduce, options, callback) {
mapCommandHash.bypassDocumentValidation = options.bypassDocumentValidation;
}
+ // Have we specified collation
+ decorateWithCollation(mapCommandHash, self, options);
+
// Execute command
self.s.db.command(mapCommandHash, {readPreference:options.readPreference}, function (err, result) {
if(err) return handleCallback(callback, err);
@@ -3205,18 +3304,18 @@ var getReadPreference = function(self, options, db, coll) {
r = options.readPreference
} else if(self.s.readPreference) {
r = self.s.readPreference
- } else if(db.readPreference) {
- r = db.readPreference;
+ } else if(db.s.readPreference) {
+ r = db.s.readPreference;
}
if(r instanceof ReadPreference) {
- options.readPreference = new CoreReadPreference(r.mode, r.tags);
+ options.readPreference = new CoreReadPreference(r.mode, r.tags, {maxStalenessMS: r.maxStalenessMS});
} else if(typeof r == 'string') {
options.readPreference = new CoreReadPreference(r);
} else if(r && !(r instanceof ReadPreference) && typeof r == 'object') {
var mode = r.mode || r.preference;
if (mode && typeof mode == 'string') {
- options.readPreference = new CoreReadPreference(mode, r.tags);
+ options.readPreference = new CoreReadPreference(mode, r.tags, {maxStalenessMS: r.maxStalenessMS});
}
}
@@ -3227,6 +3326,7 @@ var testForFields = {
limit: 1, sort: 1, fields:1, skip: 1, hint: 1, explain: 1, snapshot: 1, timeout: 1, tailable: 1, tailableRetryInterval: 1
, numberOfRetries: 1, awaitdata: 1, awaitData: 1, exhaust: 1, batchSize: 1, returnKey: 1, maxScan: 1, min: 1, max: 1, showDiskLoc: 1
, comment: 1, raw: 1, readPreference: 1, partial: 1, read: 1, dbName: 1, oplogReplay: 1, connection: 1, maxTimeMS: 1, transforms: 1
+ , collation: 1
}
module.exports = Collection;
diff --git a/node_modules/mongodb/lib/command_cursor.js b/node_modules/mongodb/lib/command_cursor.js
index 94c5234..c0d86ca 100644
--- a/node_modules/mongodb/lib/command_cursor.js
+++ b/node_modules/mongodb/lib/command_cursor.js
@@ -163,7 +163,7 @@ CommandCursor.prototype.setReadPreference = function(r) {
if(this.s.state != CommandCursor.INIT) throw MongoError.create({message: 'cannot change cursor readPreference after cursor has been accessed', driver:true});
if(r instanceof ReadPreference) {
- this.s.options.readPreference = new CoreReadPreference(r.mode, r.tags);
+ this.s.options.readPreference = new CoreReadPreference(r.mode, r.tags, {maxStalenessMS: r.maxStalenessMS});
} else if(typeof r == 'string') {
this.s.options.readPreference = new CoreReadPreference(r);
} else if(r instanceof CoreReadPreference) {
diff --git a/node_modules/mongodb/lib/cursor.js b/node_modules/mongodb/lib/cursor.js
index 9000847..f62b6d6 100644
--- a/node_modules/mongodb/lib/cursor.js
+++ b/node_modules/mongodb/lib/cursor.js
@@ -579,6 +579,20 @@ Cursor.prototype.batchSize = function(value) {
define.classMethod('batchSize', {callback: false, promise:false, returns: [Cursor]});
/**
+ * Set the collation options for the cursor.
+ * @method
+ * @param {object} value The cursor collation options
+ * @throws {MongoError}
+ * @return {Cursor}
+ */
+Cursor.prototype.collation = function(value) {
+ this.s.cmd.collation = value;
+ return this;
+}
+
+define.classMethod('collation', {callback: false, promise:false, returns: [Cursor]});
+
+/**
* Set the limit for the cursor.
* @method
* @param {number} value The limit for the cursor query.
@@ -779,7 +793,7 @@ define.classMethod('forEach', {callback: true, promise:false});
Cursor.prototype.setReadPreference = function(r) {
if(this.s.state != Cursor.INIT) throw MongoError.create({message: 'cannot change cursor readPreference after cursor has been accessed', driver:true});
if(r instanceof ReadPreference) {
- this.s.options.readPreference = new CoreReadPreference(r.mode, r.tags);
+ this.s.options.readPreference = new CoreReadPreference(r.mode, r.tags, {maxStalenessMS: r.maxStalenessMS});
} else if(typeof r == 'string'){
this.s.options.readPreference = new CoreReadPreference(r);
} else if(r instanceof CoreReadPreference) {
@@ -879,7 +893,7 @@ define.classMethod('toArray', {callback: true, promise:true});
/**
* Get the count of documents for this cursor
* @method
- * @param {boolean} applySkipLimit Should the count command apply limit and skip settings on the cursor or in the passed in options.
+ * @param {boolean} [applySkipLimit=true] Should the count command apply limit and skip settings on the cursor or in the passed in options.
* @param {object} [options=null] Optional settings.
* @param {number} [options.skip=null] The number of documents to skip.
* @param {number} [options.limit=null] The maximum amounts to count before aborting.
diff --git a/node_modules/mongodb/lib/db.js b/node_modules/mongodb/lib/db.js
index a51ca0b..e6eadc4 100644
--- a/node_modules/mongodb/lib/db.js
+++ b/node_modules/mongodb/lib/db.js
@@ -47,7 +47,7 @@ var debugFields = ['authSource', 'w', 'wtimeout', 'j', 'native_parser', 'forceSe
var legalOptionNames = ['w', 'wtimeout', 'fsync', 'j', 'readPreference', 'readPreferenceTags', 'native_parser'
, 'forceServerObjectId', 'pkFactory', 'serializeFunctions', 'raw', 'bufferMaxEntries', 'authSource'
, 'ignoreUndefined', 'promoteLongs', 'promiseLibrary', 'readConcern', 'retryMiliSeconds', 'numberOfRetries'
- , 'parentDb', 'noListener', 'loggerLevel', 'logger'];
+ , 'parentDb', 'noListener', 'loggerLevel', 'logger', 'collation'];
/**
* Creates a new Db instance
@@ -143,6 +143,8 @@ var Db = function(databaseName, topology, options) {
, noListener: typeof options.noListener == 'boolean' ? options.noListener : false
// ReadConcern
, readConcern: options.readConcern
+ // Collation
+ , collation: options.collation
}
// Ensure we have a valid db name
@@ -262,11 +264,11 @@ var convertReadPreference = function(readPreference) {
if(readPreference && typeof readPreference == 'string') {
return new CoreReadPreference(readPreference);
} else if(readPreference instanceof ReadPreference) {
- return new CoreReadPreference(readPreference.mode, readPreference.tags);
+ return new CoreReadPreference(readPreference.mode, readPreference.tags, {maxStalenessMS: readPreference.maxStalenessMS});
} else if(readPreference && typeof readPreference == 'object') {
var mode = readPreference.mode || readPreference.preference;
if (mode && typeof mode == 'string') {
- readPreference = new CoreReadPreference(mode, readPreference.tags);
+ readPreference = new CoreReadPreference(mode, readPreference.tags, {maxStalenessMS: readPreference.maxStalenessMS});
}
}
return readPreference;
@@ -437,6 +439,11 @@ Db.prototype.collection = function(name, options, callback) {
// If we have not set a collection level readConcern set the db level one
options.readConcern = options.readConcern || this.s.readConcern;
+ // Do we have a db level collation but not one for the collection
+ if(!options.collation && this.s.collation && typeof this.s.collation == 'object') {
+ options.collation = this.s.collation;
+ }
+
// Do we have ignoreUndefined set
if(this.s.options.ignoreUndefined) {
options.ignoreUndefined = this.s.options.ignoreUndefined;
@@ -479,6 +486,18 @@ Db.prototype.collection = function(name, options, callback) {
define.classMethod('collection', {callback: true, promise:false, returns: [Collection]});
+function decorateWithWriteConcern(command, self, options) {
+ // Do we support write concerns 3.4 and higher
+ if(self.s.topology.capabilities().commandsTakeWriteConcern) {
+ // Get the write concern settings
+ var finalOptions = writeConcern(shallowClone(options), self, options);
+ // Add the write concern to the command
+ if(finalOptions.writeConcern) {
+ command.writeConcern = finalOptions.writeConcern;
+ }
+ }
+}
+
var createCollection = function(self, name, options, callback) {
// Get the write concern options
var finalOptions = writeConcern(shallowClone(options), self, options);
@@ -500,6 +519,9 @@ var createCollection = function(self, name, options, callback) {
// Create collection command
var cmd = {'create':name};
+ // Decorate command with writeConcern if supported
+ decorateWithWriteConcern(cmd, self, options);
+
// Add all optional parameters
for(var n in options) {
if(options[n] != null && typeof options[n] != 'function')
@@ -799,11 +821,14 @@ define.classMethod('renameCollection', {callback: true, promise:true});
Db.prototype.dropCollection = function(name, options, callback) {
var self = this;
if(typeof options == 'function') callback = options, options = {};
- options = options | {};
+ options = options || {};
// Command to execute
var cmd = {'drop':name}
+ // Decorate with write concern
+ decorateWithWriteConcern(cmd, self, options);
+
// options
options = assign({}, this.s.options, {readPreference: ReadPreference.PRIMARY});
@@ -843,10 +868,15 @@ define.classMethod('dropCollection', {callback: true, promise:true});
* @param {Db~resultCallback} [callback] The results callback
* @return {Promise} returns Promise if no callback passed
*/
-Db.prototype.dropDatabase = function(callback) {
+Db.prototype.dropDatabase = function(options, callback) {
var self = this;
+ if(typeof options == 'function') callback = options, options = {};
// Drop database command
var cmd = {'dropDatabase':1};
+
+ // Decorate with write concern
+ decorateWithWriteConcern(cmd, self, options);
+
// Ensure primary only
var options = assign({}, this.s.options, {readPreference: ReadPreference.PRIMARY});
@@ -1132,29 +1162,28 @@ Db.prototype.addChild = function(db) {
*/
Db.prototype.db = function(dbName, options) {
options = options || {};
+
// Copy the options and add out internal override of the not shared flag
- for(var key in this.options) {
- options[key] = this.options[key];
- }
+ var finalOptions = assign({}, this.options, options);
// Do we have the db in the cache already
- if(this.s.dbCache[dbName] && options.returnNonCachedInstance !== true) {
+ if(this.s.dbCache[dbName] && finalOptions.returnNonCachedInstance !== true) {
return this.s.dbCache[dbName];
}
// Add current db as parentDb
- if(options.noListener == null || options.noListener == false) {
- options.parentDb = this;
+ if(finalOptions.noListener == null || finalOptions.noListener == false) {
+ finalOptions.parentDb = this;
}
// Add promiseLibrary
- options.promiseLibrary = this.s.promiseLibrary;
+ finalOptions.promiseLibrary = this.s.promiseLibrary;
// Return the db object
- var db = new Db(dbName, this.s.topology, options)
+ var db = new Db(dbName, this.s.topology, finalOptions)
// Add as child
- if(options.noListener == null || options.noListener == false) {
+ if(finalOptions.noListener == null || finalOptions.noListener == false) {
this.addChild(db);
}
@@ -1700,9 +1729,24 @@ var createIndexUsingCreateIndexes = function(self, name, fieldOrSpec, options, c
}
}
+ // Get capabilities
+ var capabilities = self.s.topology.capabilities();
+
+ // Did the user pass in a collation, check if our write server supports it
+ if(indexes[0].collation && capabilities && !capabilities.commandsTakeCollation) {
+ // Create a new error
+ var error = new MongoError(f('server/primary/mongos does not support collation'));
+ error.code = 67;
+ // Return the error
+ return callback(error);
+ }
+
// Create command, apply write concern to command
var cmd = writeConcern({createIndexes: name, indexes: indexes}, self, options);
+ // Decorate command with writeConcern if supported
+ decorateWithWriteConcern(cmd, self, options);
+
// ReadPreference primary
options.readPreference = ReadPreference.PRIMARY;
diff --git a/node_modules/mongodb/lib/mongo_client.js b/node_modules/mongodb/lib/mongo_client.js
index 8017604..6de464d 100644
--- a/node_modules/mongodb/lib/mongo_client.js
+++ b/node_modules/mongodb/lib/mongo_client.js
@@ -7,9 +7,10 @@ var parse = require('./url_parser')
, Define = require('./metadata')
, ReadPreference = require('./read_preference')
, Logger = require('mongodb-core').Logger
+ , MongoError = require('mongodb-core').MongoError
, Db = require('./db')
, dns = require('dns')
- , f = require('util').format
+ , f = require('util').format
, shallowClone = require('./utils').shallowClone;
/**
@@ -130,9 +131,12 @@ var mergeOptions = function(target, source, flatten) {
var createUnifiedOptions = function(finalOptions, options) {
var childOptions = ['mongos', 'server', 'db'
, 'replset', 'db_options', 'server_options', 'rs_options', 'mongos_options'];
+ var noMerge = ['collation'];
for(var name in options) {
- if(childOptions.indexOf(name.toLowerCase()) != -1) {
+ if(noMerge.indexOf(name.toLowerCase()) != -1) {
+ finalOptions[name] = options[name];
+ } else if(childOptions.indexOf(name.toLowerCase()) != -1) {
finalOptions = mergeOptions(finalOptions, options[name], false);
} else {
if(options[name] && typeof options[name] == 'object' && !Buffer.isBuffer(options[name]) && !Array.isArray(options[name])) {
@@ -157,9 +161,14 @@ function translateOptions(options) {
options.readPreference.tags = options.readPreferenceTags || options.read_preference_tags;
}
+ // Do we have maxStalenessMS
+ if(options.maxStalenessMS) {
+ options.readPreference.maxStalenessMS = options.maxStalenessMS;
+ }
+
// Set the socket and connection timeouts
- if(!options.socketTimeoutMS) options.socketTimeoutMS = 30000;
- if(!options.connectTimeoutMS) options.connectTimeoutMS = 30000;
+ if(!options.socketTimeoutMS == null) options.socketTimeoutMS = 30000;
+ if(!options.connectTimeoutMS == null) options.connectTimeoutMS = 30000;
// Create server instances
return options.servers.map(function(serverObj) {
@@ -269,21 +278,35 @@ var connect = function(url, options, callback) {
_finalOptions = createUnifiedOptions(_finalOptions, options);
// Check if we have connection and socket timeout set
- if(!_finalOptions.socketTimeoutMS) _finalOptions.socketTimeoutMS = 120000;
- if(!_finalOptions.connectTimeoutMS) _finalOptions.connectTimeoutMS = 120000;
+ if(!_finalOptions.socketTimeoutMS == null) _finalOptions.socketTimeoutMS = 120000;
+ if(!_finalOptions.connectTimeoutMS == null) _finalOptions.connectTimeoutMS = 120000;
// Failure modes
if(object.servers.length == 0) {
throw new Error("connection string must contain at least one seed host");
}
+ function connectCallback(err, db) {
+ if(err && err.message == 'no mongos proxies found in seed list') {
+ if(logger.isWarn()) {
+ logger.warn(f('seed list contains no mongos proxies, replicaset connections requires the parameter replicaSet to be supplied in the URI or options object, mongodb://server:port/db?replicaSet=name'));
+ }
+
+ // Return a more specific error message for MongoClient.connect
+ return callback(new MongoError('seed list contains no mongos proxies, replicaset connections requires the parameter replicaSet to be supplied in the URI or options object, mongodb://server:port/db?replicaSet=name'));
+ }
+
+ // Return the error and db instance
+ callback(err, db);
+ }
+
// Do we have a replicaset then skip discovery and go straight to connectivity
if(_finalOptions.replicaSet || _finalOptions.rs_name) {
- return createReplicaset(_finalOptions, connectHandler(_finalOptions, callback));
+ return createReplicaset(_finalOptions, connectHandler(_finalOptions, connectCallback));
} else if(object.servers.length > 1) {
- return createMongos(_finalOptions, connectHandler(_finalOptions, callback));
+ return createMongos(_finalOptions, connectHandler(_finalOptions, connectCallback));
} else {
- return createServer(_finalOptions, connectHandler(_finalOptions, callback));
+ return createServer(_finalOptions, connectHandler(_finalOptions, connectCallback));
}
}
diff --git a/node_modules/mongodb/lib/mongos.js b/node_modules/mongodb/lib/mongos.js
index 460f93f..b6e4635 100644
--- a/node_modules/mongodb/lib/mongos.js
+++ b/node_modules/mongodb/lib/mongos.js
@@ -17,7 +17,16 @@ var EventEmitter = require('events').EventEmitter
, MAX_JS_INT = require('./utils').MAX_JS_INT
, translateOptions = require('./utils').translateOptions
, filterOptions = require('./utils').filterOptions
- , mergeOptions = require('./utils').mergeOptions;
+ , mergeOptions = require('./utils').mergeOptions
+ , os = require('os');
+
+// Get package.json variable
+var driverVersion = require(__dirname + '/../package.json').version;
+var nodejsversion = f('Node.js %s, %s', process.version, os.endianness());
+var type = os.type();
+var name = process.platform;
+var architecture = process.arch;
+var release = os.release();
/**
* @fileOverview The **Mongos** class is a class that represents a Mongos Proxy topology and is
@@ -44,7 +53,7 @@ var EventEmitter = require('events').EventEmitter
, 'sslCA', 'sslCert', 'sslKey', 'sslPass', 'socketOptions', 'bufferMaxEntries'
, 'store', 'auto_reconnect', 'autoReconnect', 'emitError'
, 'keepAlive', 'noDelay', 'connectTimeoutMS', 'socketTimeoutMS'
- , 'loggerLevel', 'logger', 'reconnectTries'];
+ , 'loggerLevel', 'logger', 'reconnectTries', 'appname', 'domainsEnabled'];
/**
* Creates a new Mongos instance
@@ -68,6 +77,7 @@ var EventEmitter = require('events').EventEmitter
* @param {number} [options.socketOptions.keepAlive=0] TCP KeepAlive on the socket with a X ms delay before start.
* @param {number} [options.socketOptions.connectTimeoutMS=0] TCP Connection timeout setting
* @param {number} [options.socketOptions.socketTimeoutMS=0] TCP Socket timeout setting
+ * @param {boolean} [options.domainsEnabled=false] Enable the wrapping of the callback in the current domain, disabled by default to avoid perf hit.
* @fires Mongos#connect
* @fires Mongos#ha
* @fires Mongos#joined
@@ -139,6 +149,28 @@ var Mongos = function(servers, options) {
clonedOptions.keepAlive = clonedOptions.keepAlive > 0;
}
+ // Build default client information
+ this.clientInfo = {
+ driver: {
+ name: "nodejs",
+ version: driverVersion
+ },
+ os: {
+ type: type,
+ name: name,
+ architecture: architecture,
+ version: release
+ },
+ platform: nodejsversion
+ }
+
+ // Build default client information
+ clonedOptions.clientInfo = this.clientInfo;
+ // Do we have an application specific string
+ if(options.appname) {
+ clonedOptions.clientInfo.application = { name: options.appname };
+ }
+
// Create the Mongos
var mongos = new CMongos(seedlist, clonedOptions)
// Server capabilities
diff --git a/node_modules/mongodb/lib/read_preference.js b/node_modules/mongodb/lib/read_preference.js
index 73b253a..0c8da2b 100644
--- a/node_modules/mongodb/lib/read_preference.js
+++ b/node_modules/mongodb/lib/read_preference.js
@@ -3,7 +3,7 @@
/**
* @fileOverview The **ReadPreference** class is a class that represents a MongoDB ReadPreference and is
* used to construct connections.
- *
+ *
* @example
* var Db = require('mongodb').Db,
* ReplSet = require('mongodb').ReplSet,
@@ -27,7 +27,7 @@
/**
* Creates a new ReadPreference instance
- *
+ *
* Read Preferences
* - **ReadPreference.PRIMARY**, Read from primary only. All operations produce an error (throw an exception where applicable) if primary is unavailable. Cannot be combined with tags (This is the default.).
* - **ReadPreference.PRIMARY_PREFERRED**, Read from primary if available, otherwise a secondary.
@@ -37,17 +37,34 @@
*
* @class
* @param {string} mode The ReadPreference mode as listed above.
- * @param {object} tags An object representing read preference tags.
+ * @param {array} tags An object representing read preference tags.
+ * @param {object} [options] Additional read preference options
+ * @param {number} [options.maxStalenessMS] Max Secondary Read Stalleness in Miliseconds
* @property {string} mode The ReadPreference mode.
- * @property {object} tags The ReadPreference tags.
+ * @property {array} tags The ReadPreference tags.
+ * @property {object} options Additional read preference options
+ * @property {number} maxStalenessMS MaxStalenessMS value for the read preference
* @return {ReadPreference} a ReadPreference instance.
- */
-var ReadPreference = function(mode, tags) {
- if(!(this instanceof ReadPreference))
- return new ReadPreference(mode, tags);
+ */
+var ReadPreference = function(mode, tags, options) {
+ if(!(this instanceof ReadPreference)) {
+ return new ReadPreference(mode, tags, options);
+ }
+
this._type = 'ReadPreference';
this.mode = mode;
this.tags = tags;
+ this.options = options;
+
+ // If no tags were passed in
+ if(tags && typeof tags == 'object') {
+ this.options = tags, this.tags = null;
+ }
+
+ // Add the maxStalenessMS value to the read Preference
+ if(this.options && this.options.maxStalenessMS) {
+ this.maxStalenessMS = this.options.maxStalenessMS;
+ }
}
/**
@@ -56,7 +73,7 @@ var ReadPreference = function(mode, tags) {
* @method
* @param {string} mode The string representing the read preference mode.
* @return {boolean}
- */
+ */
ReadPreference.isValid = function(_mode) {
return (_mode == ReadPreference.PRIMARY || _mode == ReadPreference.PRIMARY_PREFERRED
|| _mode == ReadPreference.SECONDARY || _mode == ReadPreference.SECONDARY_PREFERRED
@@ -70,7 +87,7 @@ ReadPreference.isValid = function(_mode) {
* @method
* @param {string} mode The string representing the read preference mode.
* @return {boolean}
- */
+ */
ReadPreference.prototype.isValid = function(mode) {
var _mode = typeof mode == 'string' ? mode : this.mode;
return ReadPreference.isValid(_mode);
@@ -86,12 +103,23 @@ ReadPreference.prototype.toObject = function() {
object['tags'] = this.tags;
}
+ if(this.maxStalenessMS) {
+ object['maxStalenessMS'] = this.maxStalenessMS;
+ }
+
return object;
}
/**
* @ignore
*/
+ReadPreference.prototype.toJSON = function() {
+ return this.toObject();
+}
+
+/**
+ * @ignore
+ */
ReadPreference.PRIMARY = 'primary';
ReadPreference.PRIMARY_PREFERRED = 'primaryPreferred';
ReadPreference.SECONDARY = 'secondary';
@@ -101,4 +129,4 @@ ReadPreference.NEAREST = 'nearest'
/**
* @ignore
*/
-module.exports = ReadPreference; \ No newline at end of file
+module.exports = ReadPreference;
diff --git a/node_modules/mongodb/lib/replset.js b/node_modules/mongodb/lib/replset.js
index d740464..5bf6026 100644
--- a/node_modules/mongodb/lib/replset.js
+++ b/node_modules/mongodb/lib/replset.js
@@ -21,8 +21,8 @@ var EventEmitter = require('events').EventEmitter
, MAX_JS_INT = require('./utils').MAX_JS_INT
, translateOptions = require('./utils').translateOptions
, filterOptions = require('./utils').filterOptions
- , mergeOptions = require('./utils').mergeOptions;
-
+ , mergeOptions = require('./utils').mergeOptions
+ , os = require('os');
/**
* @fileOverview The **ReplSet** class is a class that represents a Replicaset topology and is
* used to construct connections.
@@ -48,7 +48,15 @@ var legalOptionNames = ['ha', 'haInterval', 'replicaSet', 'rs_name', 'secondaryA
, 'sslCA', 'sslCert', 'sslKey', 'sslPass', 'socketOptions', 'bufferMaxEntries'
, 'store', 'auto_reconnect', 'autoReconnect', 'emitError'
, 'keepAlive', 'noDelay', 'connectTimeoutMS', 'socketTimeoutMS', 'strategy', 'debug'
- , 'loggerLevel', 'logger', 'reconnectTries'];
+ , 'loggerLevel', 'logger', 'reconnectTries', 'appname', 'domainsEnabled'];
+
+// Get package.json variable
+var driverVersion = require(__dirname + '/../package.json').version;
+var nodejsversion = f('Node.js %s, %s', process.version, os.endianness());
+var type = os.type();
+var name = process.platform;
+var architecture = process.arch;
+var release = os.release();
/**
* Creates a new ReplSet instance
@@ -74,6 +82,7 @@ var legalOptionNames = ['ha', 'haInterval', 'replicaSet', 'rs_name', 'secondaryA
* @param {number} [options.socketOptions.keepAlive=0] TCP KeepAlive on the socket with a X ms delay before start.
* @param {number} [options.socketOptions.connectTimeoutMS=10000] TCP Connection timeout setting
* @param {number} [options.socketOptions.socketTimeoutMS=0] TCP Socket timeout setting
+ * @param {boolean} [options.domainsEnabled=false] Enable the wrapping of the callback in the current domain, disabled by default to avoid perf hit.
* @fires ReplSet#connect
* @fires ReplSet#ha
* @fires ReplSet#joined
@@ -117,13 +126,6 @@ var ReplSet = function(servers, options) {
return {host: x.host, port: x.port}
});
- // console.log("!!!!!!!!!!!!!!!!!!!!!!!!!! RECONNECT")
- // console.dir(options)
-
- // // Get the reconnect option
- // var reconnect = typeof options.auto_reconnect == 'boolean' ? options.auto_reconnect : false;
- // reconnect = typeof options.autoReconnect == 'boolean' ? options.autoReconnect : reconnect;
-
// Clone options
var clonedOptions = mergeOptions({}, {
disconnectHandler: store,
@@ -147,8 +149,28 @@ var ReplSet = function(servers, options) {
clonedOptions.keepAlive = clonedOptions.keepAlive > 0;
}
- // console.log("=============== create CReplSet")
- // console.dir(clonedOptions)
+ // Client info
+ this.clientInfo = {
+ driver: {
+ name: "nodejs",
+ version: driverVersion
+ },
+ os: {
+ type: type,
+ name: name,
+ architecture: architecture,
+ version: release
+ },
+ platform: nodejsversion
+ }
+
+ // Build default client information
+ clonedOptions.clientInfo = this.clientInfo;
+ // Do we have an application specific string
+ if(options.appname) {
+ clonedOptions.clientInfo.application = { name: options.appname };
+ }
+
// Create the ReplSet
var replset = new CReplSet(seedlist, clonedOptions);
// Server capabilities
@@ -216,7 +238,7 @@ var translateReadPreference = function(options) {
options.readPreference = new CoreReadPreference(options.readPreference);
} else if(options.readPreference instanceof ReadPreference) {
options.readPreference = new CoreReadPreference(options.readPreference.mode
- , options.readPreference.tags);
+ , options.readPreference.tags, {maxStalenessMS: options.readPreference.maxStalenessMS});
}
return options;
diff --git a/node_modules/mongodb/lib/server.js b/node_modules/mongodb/lib/server.js
index cf5ba5a..78684bb 100644
--- a/node_modules/mongodb/lib/server.js
+++ b/node_modules/mongodb/lib/server.js
@@ -15,7 +15,16 @@ var EventEmitter = require('events').EventEmitter
, MAX_JS_INT = require('./utils').MAX_JS_INT
, translateOptions = require('./utils').translateOptions
, filterOptions = require('./utils').filterOptions
- , mergeOptions = require('./utils').mergeOptions;
+ , mergeOptions = require('./utils').mergeOptions
+ , os = require('os');
+
+// Get package.json variable
+var driverVersion = require(__dirname + '/../package.json').version;
+var nodejsversion = f('Node.js %s, %s', process.version, os.endianness());
+var type = os.type();
+var name = process.platform;
+var architecture = process.arch;
+var release = os.release();
/**
* @fileOverview The **Server** class is a class that represents a single server topology and is
@@ -40,7 +49,8 @@ var EventEmitter = require('events').EventEmitter
, 'sslCA', 'sslCert', 'sslKey', 'sslPass', 'socketOptions', 'bufferMaxEntries'
, 'store', 'auto_reconnect', 'autoReconnect', 'emitError'
, 'keepAlive', 'noDelay', 'connectTimeoutMS', 'socketTimeoutMS'
- , 'loggerLevel', 'logger', 'reconnectTries', 'reconnectInterval', 'monitoring'];
+ , 'loggerLevel', 'logger', 'reconnectTries', 'reconnectInterval', 'monitoring'
+ , 'appname', 'domainsEnabled'];
/**
* Creates a new Server instance
@@ -67,6 +77,7 @@ var EventEmitter = require('events').EventEmitter
* @param {number} [options.reconnectInterval=1000] Server will wait # milliseconds between retries
* @param {number} [options.monitoring=true] Triggers the server instance to call ismaster
* @param {number} [options.haInterval=10000] The interval of calling ismaster when monitoring is enabled.
+ * @param {boolean} [options.domainsEnabled=false] Enable the wrapping of the callback in the current domain, disabled by default to avoid perf hit.
* @fires Server#connect
* @fires Server#close
* @fires Server#error
@@ -130,6 +141,28 @@ var Server = function(host, port, options) {
clonedOptions.keepAlive = clonedOptions.keepAlive > 0;
}
+ // Build default client information
+ this.clientInfo = {
+ driver: {
+ name: "nodejs",
+ version: driverVersion
+ },
+ os: {
+ type: type,
+ name: name,
+ architecture: architecture,
+ version: release
+ },
+ platform: nodejsversion
+ }
+
+ // Build default client information
+ clonedOptions.clientInfo = this.clientInfo;
+ // Do we have an application specific string
+ if(options.appname) {
+ clonedOptions.clientInfo.application = { name: options.appname };
+ }
+
// Create an instance of a server instance from mongodb-core
var server = new CServer(clonedOptions);
// Server capabilities
diff --git a/node_modules/mongodb/lib/topology_base.js b/node_modules/mongodb/lib/topology_base.js
index cad8d85..2f5ac1f 100644
--- a/node_modules/mongodb/lib/topology_base.js
+++ b/node_modules/mongodb/lib/topology_base.js
@@ -113,6 +113,8 @@ var ServerCapabilities = function(ismaster) {
var listCollections = false;
var listIndexes = false;
var maxNumberOfDocsInBatch = ismaster.maxWriteBatchSize || 1000;
+ var commandsTakeWriteConcern = false;
+ var commandsTakeCollation = false;
if(ismaster.minWireVersion >= 0) {
textSearch = true;
@@ -132,6 +134,11 @@ var ServerCapabilities = function(ismaster) {
listIndexes = true;
}
+ if(ismaster.maxWireVersion >= 5) {
+ commandsTakeWriteConcern = true;
+ commandsTakeCollation = true;
+ }
+
// If no min or max wire version set to 0
if(ismaster.minWireVersion == null) {
ismaster.minWireVersion = 0;
@@ -151,6 +158,8 @@ var ServerCapabilities = function(ismaster) {
setup_get_property(this, "minWireVersion", ismaster.minWireVersion);
setup_get_property(this, "maxWireVersion", ismaster.maxWireVersion);
setup_get_property(this, "maxNumberOfDocsInBatch", maxNumberOfDocsInBatch);
+ setup_get_property(this, "commandsTakeWriteConcern", commandsTakeWriteConcern);
+ setup_get_property(this, "commandsTakeCollation", commandsTakeCollation);
}
exports.Store = Store;
diff --git a/node_modules/mongodb/lib/url_parser.js b/node_modules/mongodb/lib/url_parser.js
index 0152612..663e5dc 100644
--- a/node_modules/mongodb/lib/url_parser.js
+++ b/node_modules/mongodb/lib/url_parser.js
@@ -223,6 +223,8 @@ module.exports = function(url, options) {
serverOptions.poolSize = parseInt(value, 10);
replSetServersOptions.poolSize = parseInt(value, 10);
break;
+ case 'appname':
+ object.appname = decodeURIComponent(value);
case 'autoReconnect':
case 'auto_reconnect':
serverOptions.auto_reconnect = (value == 'true');
@@ -353,6 +355,9 @@ module.exports = function(url, options) {
if(!ReadPreference.isValid(value)) throw new Error("readPreference must be either primary/primaryPreferred/secondary/secondaryPreferred/nearest");
dbOptions.readPreference = value;
break;
+ case 'maxStalenessMS':
+ dbOptions.maxStalenessMS = parseInt(value, 10);
+ break;
case 'readPreferenceTags':
// Decode the value
value = decodeURIComponent(value);