Skip to content

Commit ac0fee1

Browse files
committed
NODE-729 Support sending writeConcern for commands that write
1 parent 713aace commit ac0fee1

File tree

12 files changed

+1783
-14
lines changed

12 files changed

+1783
-14
lines changed

lib/collection.js

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1410,6 +1410,9 @@ var rename = function(self, newName, opt, callback) {
14101410
var dropTarget = typeof opt.dropTarget == 'boolean' ? opt.dropTarget : false;
14111411
var cmd = {'renameCollection':renameCollection, 'to':toCollection, 'dropTarget':dropTarget};
14121412

1413+
// Decorate command with writeConcern if supported
1414+
decorateWithWriteConcern(cmd, self, opt);
1415+
14131416
// Execute against admin
14141417
self.s.db.admin().command(cmd, opt, function(err, doc) {
14151418
if(err) return handleCallback(callback, err, null);
@@ -1436,10 +1439,10 @@ define.classMethod('rename', {callback: true, promise:true});
14361439
Collection.prototype.drop = function(options, callback) {
14371440
var self = this;
14381441
if(typeof options == 'function') callback = options, options = {};
1439-
options = options | {};
1442+
options = options || {};
14401443

14411444
// Execute using callback
1442-
if(typeof callback == 'function') return self.s.db.dropCollection(self.s.name, callback);
1445+
if(typeof callback == 'function') return self.s.db.dropCollection(self.s.name, options, callback);
14431446
// Return a Promise
14441447
return new this.s.promiseLibrary(function(resolve, reject) {
14451448
self.s.db.dropCollection(self.s.name, options, function(err, r) {
@@ -1645,7 +1648,10 @@ Collection.prototype.dropIndex = function(indexName, options, callback) {
16451648

16461649
var dropIndex = function(self, indexName, options, callback) {
16471650
// Delete index command
1648-
var cmd = {'deleteIndexes':self.s.name, 'index':indexName};
1651+
var cmd = {'dropIndexes':self.s.name, 'index':indexName};
1652+
1653+
// Decorate command with writeConcern if supported
1654+
decorateWithWriteConcern(cmd, self, options);
16491655

16501656
// Execute command
16511657
self.s.db.command(cmd, options, function(err, result) {
@@ -1663,11 +1669,15 @@ define.classMethod('dropIndex', {callback: true, promise:true});
16631669
* @param {Collection~resultCallback} [callback] The command result callback
16641670
* @return {Promise} returns Promise if no callback passed
16651671
*/
1666-
Collection.prototype.dropIndexes = function(callback) {
1672+
Collection.prototype.dropIndexes = function(options, callback) {
16671673
var self = this;
16681674

1675+
// Do we have options
1676+
if(typeof options == 'function') callback = options, options = {};
1677+
options = options || {};
1678+
16691679
// Execute using callback
1670-
if(typeof callback == 'function') return dropIndexes(self, callback);
1680+
if(typeof callback == 'function') return dropIndexes(self, options, callback);
16711681

16721682
// Return a Promise
16731683
return new this.s.promiseLibrary(function(resolve, reject) {
@@ -1678,8 +1688,8 @@ Collection.prototype.dropIndexes = function(callback) {
16781688
});
16791689
}
16801690

1681-
var dropIndexes = function(self, callback) {
1682-
self.dropIndex('*', function (err, result) {
1691+
var dropIndexes = function(self, options, callback) {
1692+
self.dropIndex('*', options, function(err, result) {
16831693
if(err) return handleCallback(callback, err, false);
16841694
handleCallback(callback, null, true);
16851695
});
@@ -1726,6 +1736,9 @@ var reIndex = function(self, options, callback) {
17261736
// Reindex
17271737
var cmd = {'reIndex':self.s.name};
17281738

1739+
// Decorate command with writeConcern if supported
1740+
decorateWithWriteConcern(cmd, self, options);
1741+
17291742
// Execute the command
17301743
self.s.db.command(cmd, options, function(err, result) {
17311744
if(callback == null) return;
@@ -1760,25 +1773,20 @@ Collection.prototype.listIndexes = function(options) {
17601773
throw new MongoError('cannot connect to server');
17611774
}
17621775

1763-
// console.log("!!!!!!!!!!!!!! HEY 0")
17641776
// We have a list collections command
17651777
if(this.s.topology.capabilities().hasListIndexesCommand) {
1766-
// console.log("!!!!!!!!!!!!!! HEY 0:1")
17671778
// Cursor options
17681779
var cursor = options.batchSize ? {batchSize: options.batchSize} : {}
17691780
// Build the command
17701781
var command = { listIndexes: this.s.name, cursor: cursor };
1771-
// console.log("!!!!!!!!!!!!!! HEY 0:2")
17721782
// Execute the cursor
17731783
var cursor = this.s.topology.cursor(f('%s.$cmd', this.s.dbName), command, options);
17741784
// Do we have a readPreference, apply it
17751785
if(options.readPreference) cursor.setReadPreference(options.readPreference);
1776-
// console.log("!!!!!!!!!!!!!! HEY 0:3")
17771786
// Return the cursor
17781787
return cursor;
17791788
}
17801789

1781-
// console.log("!!!!!!!!!!!!!! HEY 1")
17821790
// Get the namespace
17831791
var ns = f('%s.system.indexes', this.s.dbName);
17841792
// Get the query
@@ -2452,6 +2460,18 @@ var findAndRemove = function(self, query, sort, options, callback) {
24522460

24532461
define.classMethod('findAndRemove', {callback: true, promise:true});
24542462

2463+
function decorateWithWriteConcern(command, self, options) {
2464+
// Do we support write concerns 3.4 and higher
2465+
if(self.s.topology.capabilities().commandsTakeWriteConcern) {
2466+
// Get the write concern settings
2467+
var finalOptions = writeConcern(shallowClone(options), self.s.db, self, options);
2468+
// Add the write concern to the command
2469+
if(finalOptions.writeConcern) {
2470+
command.writeConcern = finalOptions.writeConcern;
2471+
}
2472+
}
2473+
}
2474+
24552475
/**
24562476
* Execute an aggregation framework pipeline against the collection, needs MongoDB >= 2.2
24572477
* @method
@@ -2469,6 +2489,7 @@ define.classMethod('findAndRemove', {callback: true, promise:true});
24692489
*/
24702490
Collection.prototype.aggregate = function(pipeline, options, callback) {
24712491
var self = this;
2492+
24722493
if(Array.isArray(pipeline)) {
24732494
// Set up callback if one is provided
24742495
if(typeof options == 'function') {
@@ -2510,6 +2531,9 @@ Collection.prototype.aggregate = function(pipeline, options, callback) {
25102531
// Build the command
25112532
var command = { aggregate : this.s.name, pipeline : pipeline};
25122533

2534+
// Decorate command with writeConcern if supported
2535+
decorateWithWriteConcern(command, self, options);
2536+
25132537
// If we have bypassDocumentValidation set
25142538
if(typeof options.bypassDocumentValidation == 'boolean') {
25152539
command.bypassDocumentValidation = options.bypassDocumentValidation;
@@ -3085,7 +3109,10 @@ var mapReduce = function(self, map, reduce, options, callback) {
30853109
// If we have a read preference and inline is not set as output fail hard
30863110
if((options.readPreference != false && options.readPreference != 'primary')
30873111
&& options['out'] && (options['out'].inline != 1 && options['out'] != 'inline')) {
3112+
// Force readPreference to primary
30883113
options.readPreference = 'primary';
3114+
// Decorate command with writeConcern if supported
3115+
decorateWithWriteConcern(mapCommandHash, self, options);
30893116
} else if(self.s.readConcern) {
30903117
mapCommandHash.readConcern = self.s.readConcern;
30913118
}

lib/db.js

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,18 @@ Db.prototype.collection = function(name, options, callback) {
479479

480480
define.classMethod('collection', {callback: true, promise:false, returns: [Collection]});
481481

482+
function decorateWithWriteConcern(command, self, options) {
483+
// Do we support write concerns 3.4 and higher
484+
if(self.s.topology.capabilities().commandsTakeWriteConcern) {
485+
// Get the write concern settings
486+
var finalOptions = writeConcern(shallowClone(options), self, options);
487+
// Add the write concern to the command
488+
if(finalOptions.writeConcern) {
489+
command.writeConcern = finalOptions.writeConcern;
490+
}
491+
}
492+
}
493+
482494
var createCollection = function(self, name, options, callback) {
483495
// Get the write concern options
484496
var finalOptions = writeConcern(shallowClone(options), self, options);
@@ -500,6 +512,9 @@ var createCollection = function(self, name, options, callback) {
500512
// Create collection command
501513
var cmd = {'create':name};
502514

515+
// Decorate command with writeConcern if supported
516+
decorateWithWriteConcern(cmd, self, options);
517+
503518
// Add all optional parameters
504519
for(var n in options) {
505520
if(options[n] != null && typeof options[n] != 'function')
@@ -799,11 +814,14 @@ define.classMethod('renameCollection', {callback: true, promise:true});
799814
Db.prototype.dropCollection = function(name, options, callback) {
800815
var self = this;
801816
if(typeof options == 'function') callback = options, options = {};
802-
options = options | {};
817+
options = options || {};
803818

804819
// Command to execute
805820
var cmd = {'drop':name}
806821

822+
// Decorate with write concern
823+
decorateWithWriteConcern(cmd, self, options);
824+
807825
// options
808826
options = assign({}, this.s.options, {readPreference: ReadPreference.PRIMARY});
809827

@@ -843,10 +861,15 @@ define.classMethod('dropCollection', {callback: true, promise:true});
843861
* @param {Db~resultCallback} [callback] The results callback
844862
* @return {Promise} returns Promise if no callback passed
845863
*/
846-
Db.prototype.dropDatabase = function(callback) {
864+
Db.prototype.dropDatabase = function(options, callback) {
847865
var self = this;
866+
if(typeof options == 'function') callback = options, options = {};
848867
// Drop database command
849868
var cmd = {'dropDatabase':1};
869+
870+
// Decorate with write concern
871+
decorateWithWriteConcern(cmd, self, options);
872+
850873
// Ensure primary only
851874
var options = assign({}, this.s.options, {readPreference: ReadPreference.PRIMARY});
852875

@@ -1703,6 +1726,9 @@ var createIndexUsingCreateIndexes = function(self, name, fieldOrSpec, options, c
17031726
// Create command, apply write concern to command
17041727
var cmd = writeConcern({createIndexes: name, indexes: indexes}, self, options);
17051728

1729+
// Decorate command with writeConcern if supported
1730+
decorateWithWriteConcern(cmd, self, options);
1731+
17061732
// ReadPreference primary
17071733
options.readPreference = ReadPreference.PRIMARY;
17081734

lib/topology_base.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ var ServerCapabilities = function(ismaster) {
113113
var listCollections = false;
114114
var listIndexes = false;
115115
var maxNumberOfDocsInBatch = ismaster.maxWriteBatchSize || 1000;
116+
var commandsTakeWriteConcern = false;
116117

117118
if(ismaster.minWireVersion >= 0) {
118119
textSearch = true;
@@ -132,6 +133,10 @@ var ServerCapabilities = function(ismaster) {
132133
listIndexes = true;
133134
}
134135

136+
if(ismaster.maxWireVersion >= 5) {
137+
commandsTakeWriteConcern = true;
138+
}
139+
135140
// If no min or max wire version set to 0
136141
if(ismaster.minWireVersion == null) {
137142
ismaster.minWireVersion = 0;
@@ -151,6 +156,7 @@ var ServerCapabilities = function(ismaster) {
151156
setup_get_property(this, "minWireVersion", ismaster.minWireVersion);
152157
setup_get_property(this, "maxWireVersion", ismaster.maxWireVersion);
153158
setup_get_property(this, "maxNumberOfDocsInBatch", maxNumberOfDocsInBatch);
159+
setup_get_property(this, "commandsTakeWriteConcern", commandsTakeWriteConcern);
154160
}
155161

156162
exports.Store = Store;

0 commit comments

Comments
 (0)