Skip to content

Commit a531f05

Browse files
committed
feat(sessions): support passing sessions via objects in all methods
* ensure all cases where executeOperation is called, that we are also passing options * ensure in all cases where options appear, we default to {} if they are not present * remove `session` in a number of cases where commands are decorated with passed in options * all commands in cursor should use `skipSessions` because the `getMore` command uses the cached session for the cursor * `startSession` now uses the porcelain version of the topology, * delegating all relevant methods and properties down to the `coreTopology` it wraps. * modified all tests using mock servers to support `endSessions` commands NODE-1088
1 parent 34932b4 commit a531f05

23 files changed

+420
-109
lines changed

lib/admin.js

+17-8
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,12 @@ define.classMethod('command', { callback: true, promise: true });
8989
*/
9090
Admin.prototype.buildInfo = function(options, callback) {
9191
if (typeof options === 'function') (callback = options), (options = {});
92+
options = options || {};
9293

9394
const cmd = { buildinfo: 1 };
9495
return executeOperation(this.s.db.s.topology, this.s.db.executeDbAdminCommand.bind(this.s.db), [
9596
cmd,
96-
undefined,
97+
options,
9798
callback
9899
]);
99100
};
@@ -111,6 +112,7 @@ define.classMethod('buildInfo', { callback: true, promise: true });
111112
*/
112113
Admin.prototype.serverInfo = function(options, callback) {
113114
if (typeof options === 'function') (callback = options), (options = {});
115+
options = options || {};
114116

115117
const cmd = { buildinfo: 1 };
116118
return executeOperation(this.s.db.s.topology, this.s.db.executeDbAdminCommand.bind(this.s.db), [
@@ -132,6 +134,8 @@ define.classMethod('serverInfo', { callback: true, promise: true });
132134
*/
133135
Admin.prototype.serverStatus = function(options, callback) {
134136
if (typeof options === 'function') (callback = options), (options = {});
137+
options = options || {};
138+
135139
return executeOperation(this.s.db.s.topology, serverStatus, [this, options, callback]);
136140
};
137141

@@ -158,6 +162,7 @@ define.classMethod('serverStatus', { callback: true, promise: true });
158162
*/
159163
Admin.prototype.ping = function(options, callback) {
160164
if (typeof options === 'function') (callback = options), (options = {});
165+
options = options || {};
161166

162167
const cmd = { ping: 1 };
163168
return executeOperation(this.s.db.s.topology, this.s.db.executeDbAdminCommand.bind(this.s.db), [
@@ -272,13 +277,15 @@ define.classMethod('removeUser', { callback: true, promise: true });
272277
* @return {Promise} returns Promise if no callback passed
273278
*/
274279
Admin.prototype.validateCollection = function(collectionName, options, callback) {
275-
var args = Array.prototype.slice.call(arguments, 1);
276-
callback = typeof args[args.length - 1] === 'function' ? args.pop() : undefined;
277-
278-
options = args.length ? args.shift() : {};
280+
if (typeof options === 'function') (callback = options), (options = {});
279281
options = options || {};
280282

281-
return executeOperation(this.s.db.s.topology, validateCollection, [this, collectionName, options, callback]);
283+
return executeOperation(this.s.db.s.topology, validateCollection, [
284+
this,
285+
collectionName,
286+
options,
287+
callback
288+
]);
282289
};
283290

284291
var validateCollection = function(self, collectionName, options, callback) {
@@ -287,12 +294,12 @@ var validateCollection = function(self, collectionName, options, callback) {
287294

288295
// Decorate command with extra options
289296
for (var i = 0; i < keys.length; i++) {
290-
if (options.hasOwnProperty(keys[i])) {
297+
if (options.hasOwnProperty(keys[i]) && keys[i] !== 'session') {
291298
command[keys[i]] = options[keys[i]];
292299
}
293300
}
294301

295-
self.s.db.command(command, function(err, doc) {
302+
self.s.db.command(command, options, function(err, doc) {
296303
if (err != null) return callback(err, null);
297304

298305
if (doc.ok === 0) return callback(new Error('Error with validate command'), null);
@@ -343,6 +350,8 @@ define.classMethod('listDatabases', { callback: true, promise: true });
343350
*/
344351
Admin.prototype.replSetGetStatus = function(options, callback) {
345352
if (typeof options === 'function') (callback = options), (options = {});
353+
options = options || {};
354+
346355
return executeOperation(this.s.db.s.topology, replSetGetStatus, [this, options, callback]);
347356
};
348357

lib/authenticate.js

+2
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ var authenticate = function(client, username, password, options, callback) {
8181

8282
module.exports = function(self, username, password, options, callback) {
8383
if (typeof options === 'function') (callback = options), (options = {});
84+
options = options || {};
85+
8486
// Shallow copy the options
8587
options = shallowClone(options);
8688

lib/bulk/ordered.js

+8-5
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,7 @@ Object.defineProperty(OrderedBulkOperation.prototype, 'length', {
429429

430430
//
431431
// Execute next write command in a chain
432-
var executeCommands = function(self, callback) {
432+
var executeCommands = function(self, options, callback) {
433433
if (self.s.batches.length === 0) {
434434
return handleCallback(callback, null, new BulkWriteResult(self.s.bulkResult));
435435
}
@@ -484,10 +484,10 @@ var executeCommands = function(self, callback) {
484484
}
485485

486486
// Execute the next command in line
487-
executeCommands(self, callback);
487+
executeCommands(self, options, callback);
488488
};
489489

490-
var finalOptions = { ordered: true };
490+
var finalOptions = Object.assign({ ordered: true }, options);
491491
if (self.s.writeConcern != null) {
492492
finalOptions.writeConcern = self.s.writeConcern;
493493
}
@@ -563,7 +563,10 @@ var executeCommands = function(self, callback) {
563563
* @throws {MongoError}
564564
* @return {Promise} returns Promise if no callback passed
565565
*/
566-
OrderedBulkOperation.prototype.execute = function(_writeConcern, callback) {
566+
OrderedBulkOperation.prototype.execute = function(_writeConcern, options, callback) {
567+
if (typeof options === 'function') (callback = options), (options = {});
568+
options = options || {};
569+
567570
if (this.s.executed) {
568571
var executedError = toError('batch cannot be re-executed');
569572
return typeof callback === 'function'
@@ -588,7 +591,7 @@ OrderedBulkOperation.prototype.execute = function(_writeConcern, callback) {
588591
: this.s.promiseLibrary.reject(emptyBatchError);
589592
}
590593

591-
return executeOperation(this.s.topology, executeCommands, [this, callback]);
594+
return executeOperation(this.s.topology, executeCommands, [this, options, callback]);
592595
};
593596

594597
define.classMethod('execute', { callback: true, promise: false });

lib/bulk/unordered.js

+9-6
Original file line numberDiff line numberDiff line change
@@ -436,8 +436,8 @@ UnorderedBulkOperation.prototype.raw = function(op) {
436436

437437
//
438438
// Execute the command
439-
var executeBatch = function(self, batch, callback) {
440-
var finalOptions = { ordered: false };
439+
var executeBatch = function(self, batch, options, callback) {
440+
var finalOptions = Object.assign({ ordered: false }, options);
441441
if (self.s.writeConcern != null) {
442442
finalOptions.writeConcern = self.s.writeConcern;
443443
}
@@ -506,11 +506,11 @@ var executeBatch = function(self, batch, callback) {
506506

507507
//
508508
// Execute all the commands
509-
var executeBatches = function(self, callback) {
509+
var executeBatches = function(self, options, callback) {
510510
var numberOfCommandsToExecute = self.s.batches.length;
511511
// Execute over all the batches
512512
for (var i = 0; i < self.s.batches.length; i++) {
513-
executeBatch(self, self.s.batches[i], function(err) {
513+
executeBatch(self, self.s.batches[i], options, function(err) {
514514
// Count down the number of commands left to execute
515515
numberOfCommandsToExecute = numberOfCommandsToExecute - 1;
516516

@@ -575,7 +575,10 @@ var executeBatches = function(self, callback) {
575575
* @throws {MongoError}
576576
* @return {Promise} returns Promise if no callback passed
577577
*/
578-
UnorderedBulkOperation.prototype.execute = function(_writeConcern, callback) {
578+
UnorderedBulkOperation.prototype.execute = function(_writeConcern, options, callback) {
579+
if (typeof options === 'function') (callback = options), (options = {});
580+
options = options || {};
581+
579582
if (this.s.executed) {
580583
var executedError = toError('batch cannot be re-executed');
581584
return typeof callback === 'function'
@@ -602,7 +605,7 @@ UnorderedBulkOperation.prototype.execute = function(_writeConcern, callback) {
602605
: this.s.promiseLibrary.reject(emptyBatchError);
603606
}
604607

605-
return executeOperation(this.s.topology, executeBatches, [this, callback]);
608+
return executeOperation(this.s.topology, executeBatches, [this, options, callback]);
606609
};
607610

608611
define.classMethod('execute', { callback: true, promise: false });

lib/collection.js

+53-11
Original file line numberDiff line numberDiff line change
@@ -889,6 +889,7 @@ define.classMethod('insert', { callback: true, promise: true });
889889
*/
890890
Collection.prototype.updateOne = function(filter, update, options, callback) {
891891
if (typeof options === 'function') (callback = options), (options = {});
892+
options = options || {};
892893

893894
var err = checkForAtomicOperators(update);
894895
if (err) {
@@ -1013,6 +1014,7 @@ define.classMethod('replaceOne', { callback: true, promise: true });
10131014
*/
10141015
Collection.prototype.updateMany = function(filter, update, options, callback) {
10151016
if (typeof options === 'function') (callback = options), (options = {});
1017+
options = options || {};
10161018

10171019
var err = checkForAtomicOperators(update);
10181020
if (err) {
@@ -1119,13 +1121,22 @@ var updateDocuments = function(self, selector, document, options, callback) {
11191121
* @deprecated use updateOne, updateMany or bulkWrite
11201122
*/
11211123
Collection.prototype.update = function(selector, document, options, callback) {
1124+
if (typeof options === 'function') (callback = options), (options = {});
1125+
options = options || {};
1126+
11221127
// Add ignoreUndfined
11231128
if (this.s.options.ignoreUndefined) {
11241129
options = shallowClone(options);
11251130
options.ignoreUndefined = this.s.options.ignoreUndefined;
11261131
}
11271132

1128-
return executeOperation(this.s.topology, updateDocuments, [this, selector, document, options, callback]);
1133+
return executeOperation(this.s.topology, updateDocuments, [
1134+
this,
1135+
selector,
1136+
document,
1137+
options,
1138+
callback
1139+
]);
11291140
};
11301141

11311142
define.classMethod('update', { callback: true, promise: true });
@@ -1498,13 +1509,13 @@ define.classMethod('drop', { callback: true, promise: true });
14981509
*/
14991510
Collection.prototype.options = function(opts, callback) {
15001511
if (typeof opts === 'function') (callback = opts), (opts = {});
1512+
opts = opts || {};
15011513

15021514
return executeOperation(this.s.topology, options, [this, opts, callback]);
15031515
};
15041516

15051517
var options = function(self, opts, callback) {
1506-
opts = assign({}, { name: self.s.name }, opts);
1507-
self.s.db.listCollections(opts).toArray(function(err, collections) {
1518+
self.s.db.listCollections({ name: self.s.name }, opts).toArray(function(err, collections) {
15081519
if (err) return handleCallback(callback, err);
15091520
if (collections.length === 0) {
15101521
return handleCallback(
@@ -1530,6 +1541,7 @@ define.classMethod('options', { callback: true, promise: true });
15301541
*/
15311542
Collection.prototype.isCapped = function(options, callback) {
15321543
if (typeof options === 'function') (callback = options), (options = {});
1544+
options = options || {};
15331545

15341546
return executeOperation(this.s.topology, isCapped, [this, options, callback]);
15351547
};
@@ -1596,6 +1608,7 @@ define.classMethod('createIndex', { callback: true, promise: true });
15961608
*/
15971609
Collection.prototype.createIndexes = function(indexSpecs, options, callback) {
15981610
if (typeof options === 'function') (callback = options), (options = {});
1611+
options = options || {};
15991612

16001613
return executeOperation(this.s.topology, createIndexes, [this, indexSpecs, options, callback]);
16011614
};
@@ -1842,6 +1855,7 @@ define.classMethod('ensureIndex', { callback: true, promise: true });
18421855
*/
18431856
Collection.prototype.indexExists = function(indexes, options, callback) {
18441857
if (typeof options === 'function') (callback = options), (options = {});
1858+
options = options || {};
18451859

18461860
return executeOperation(this.s.topology, indexExists, [this, indexes, options, callback]);
18471861
};
@@ -1939,8 +1953,9 @@ var count = function(self, query, options, callback) {
19391953
if (hint) cmd.hint = hint;
19401954

19411955
options = shallowClone(options);
1956+
19421957
// Ensure we have the right read preference inheritance
1943-
options = getReadPreference(self, options, self.s.db, self);
1958+
options = getReadPreference(self, options, self.s.db);
19441959

19451960
// Do we have a readConcern specified
19461961
if (self.s.readConcern) {
@@ -1977,7 +1992,13 @@ Collection.prototype.distinct = function(key, query, options, callback) {
19771992
var queryOption = args.length ? args.shift() || {} : {};
19781993
var optionsOption = args.length ? args.shift() || {} : {};
19791994

1980-
return executeOperation(this.s.topology, distinct, [this, key, queryOption, optionsOption, callback]);
1995+
return executeOperation(this.s.topology, distinct, [
1996+
this,
1997+
key,
1998+
queryOption,
1999+
optionsOption,
2000+
callback
2001+
]);
19812002
};
19822003

19832004
var distinct = function(self, key, query, options, callback) {
@@ -2025,6 +2046,7 @@ define.classMethod('distinct', { callback: true, promise: true });
20252046
*/
20262047
Collection.prototype.indexes = function(options, callback) {
20272048
if (typeof options === 'function') (callback = options), (options = {});
2049+
options = options || {};
20282050

20292051
return executeOperation(this.s.topology, indexes, [this, options, callback]);
20302052
};
@@ -2148,7 +2170,13 @@ Collection.prototype.findOneAndReplace = function(filter, replacement, options,
21482170
if (replacement == null || typeof replacement !== 'object')
21492171
throw toError('replacement parameter must be an object');
21502172

2151-
return executeOperation(this.s.topology, findOneAndReplace, [this, filter, replacement, options, callback]);
2173+
return executeOperation(this.s.topology, findOneAndReplace, [
2174+
this,
2175+
filter,
2176+
replacement,
2177+
options,
2178+
callback
2179+
]);
21522180
};
21532181

21542182
var findOneAndReplace = function(self, filter, replacement, options, callback) {
@@ -2192,7 +2220,13 @@ Collection.prototype.findOneAndUpdate = function(filter, update, options, callba
21922220
if (update == null || typeof update !== 'object')
21932221
throw toError('update parameter must be an object');
21942222

2195-
return executeOperation(this.s.topology, findOneAndUpdate, [this, filter, update, options, callback]);
2223+
return executeOperation(this.s.topology, findOneAndUpdate, [
2224+
this,
2225+
filter,
2226+
update,
2227+
options,
2228+
callback
2229+
]);
21962230
};
21972231

21982232
var findOneAndUpdate = function(self, filter, update, options, callback) {
@@ -2241,7 +2275,14 @@ Collection.prototype.findAndModify = function(query, sort, doc, options, callbac
22412275
// Force read preference primary
22422276
options.readPreference = ReadPreference.PRIMARY;
22432277

2244-
return executeOperation(this.s.topology, findAndModify, [this, query, sort, doc, options, callback]);
2278+
return executeOperation(this.s.topology, findAndModify, [
2279+
this,
2280+
query,
2281+
sort,
2282+
doc,
2283+
options,
2284+
callback
2285+
]);
22452286
};
22462287

22472288
var findAndModify = function(self, query, sort, doc, options, callback) {
@@ -2679,7 +2720,8 @@ var geoNear = function(self, x, y, point, options, callback) {
26792720
var exclude = {
26802721
readPreference: true,
26812722
geoNear: true,
2682-
near: true
2723+
near: true,
2724+
session: true
26832725
};
26842726

26852727
// Filter out any excluded objects
@@ -2736,7 +2778,7 @@ var geoHaystackSearch = function(self, x, y, options, callback) {
27362778
};
27372779

27382780
// Remove read preference from hash if it exists
2739-
commandObject = decorateCommand(commandObject, options, { readPreference: true });
2781+
commandObject = decorateCommand(commandObject, options, { readPreference: true, session: true });
27402782

27412783
options = shallowClone(options);
27422784
// Ensure we have the right read preference inheritance
@@ -3014,7 +3056,7 @@ var mapReduce = function(self, map, reduce, options, callback) {
30143056
};
30153057

30163058
// Exclusion list
3017-
var exclusionList = ['readPreference'];
3059+
var exclusionList = ['readPreference', 'session'];
30183060

30193061
// Add any other options passed in
30203062
for (var n in options) {

0 commit comments

Comments
 (0)