Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/3.6' into 3.7
Browse files Browse the repository at this point in the history
  • Loading branch information
emadum committed Jul 14, 2021
2 parents 93a47fd + 6ee945e commit 91a2fc9
Show file tree
Hide file tree
Showing 39 changed files with 836 additions and 118 deletions.
11 changes: 11 additions & 0 deletions HISTORY.md
Expand Up @@ -2,6 +2,17 @@

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

### [3.6.10](https://github.com/mongodb/node-mongodb-native/compare/v3.6.9...v3.6.10) (2021-07-06)


### Bug Fixes

* **NODE-2035:** Exceptions thrown from awaited cursor forEach do not propagate ([#2852](https://github.com/mongodb/node-mongodb-native/issues/2852)) ([a917dfa](https://github.com/mongodb/node-mongodb-native/commit/a917dfada67859412344ed238796cf3bee243f5f))
* **NODE-3150:** added bsonRegExp option for v3.6 ([#2843](https://github.com/mongodb/node-mongodb-native/issues/2843)) ([e4a9a57](https://github.com/mongodb/node-mongodb-native/commit/e4a9a572427666fd1a89576dadf50b9c452e1659))
* **NODE-3358:** Command monitoring objects hold internal state references ([#2858](https://github.com/mongodb/node-mongodb-native/issues/2858)) ([750760c](https://github.com/mongodb/node-mongodb-native/commit/750760c324ddedb72491befde9f7aff1ceec009c))
* **NODE-3380:** perform retryable write checks against server ([#2861](https://github.com/mongodb/node-mongodb-native/issues/2861)) ([621677a](https://github.com/mongodb/node-mongodb-native/commit/621677a42772e0b26aa13883f57d7e42f86df43f))
* **NODE-3397:** report more helpful error with unsupported authMechanism in initial handshake ([#2876](https://github.com/mongodb/node-mongodb-native/issues/2876)) ([3ce148d](https://github.com/mongodb/node-mongodb-native/commit/3ce148d8fb37faea1ee056f6e9331e5282e65cd0))

### [3.6.9](https://github.com/mongodb/node-mongodb-native/compare/v3.6.8...v3.6.9) (2021-05-26)


Expand Down
1 change: 1 addition & 0 deletions lib/cmap/connection.js
Expand Up @@ -344,6 +344,7 @@ function write(command, options, callback) {
promoteLongs: typeof options.promoteLongs === 'boolean' ? options.promoteLongs : true,
promoteValues: typeof options.promoteValues === 'boolean' ? options.promoteValues : true,
promoteBuffers: typeof options.promoteBuffers === 'boolean' ? options.promoteBuffers : false,
bsonRegExp: typeof options.bsonRegExp === 'boolean' ? options.bsonRegExp : false,
raw: typeof options.raw === 'boolean' ? options.raw : false
};

Expand Down
9 changes: 9 additions & 0 deletions lib/collection.js
Expand Up @@ -120,6 +120,8 @@ function Collection(db, topology, dbName, name, pkFactory, options) {
options == null || options.promoteBuffers == null
? db.s.options.promoteBuffers
: options.promoteBuffers;
const bsonRegExp =
options == null || options.bsonRegExp == null ? db.s.options.bsonRegExp : options.bsonRegExp;
const collectionHint = null;

const namespace = new MongoDBNamespace(dbName, name);
Expand Down Expand Up @@ -156,6 +158,8 @@ function Collection(db, topology, dbName, name, pkFactory, options) {
promoteValues: promoteValues,
// promoteBuffers
promoteBuffers: promoteBuffers,
// bsonRegExp
bsonRegExp: bsonRegExp,
// internalHint
internalHint: internalHint,
// collectionHint
Expand Down Expand Up @@ -303,6 +307,7 @@ const DEPRECATED_FIND_OPTIONS = ['maxScan', 'fields', 'snapshot', 'oplogReplay']
* @param {boolean} [options.promoteLongs=true] Promotes Long values to number if they fit inside the 53 bits resolution.
* @param {boolean} [options.promoteValues=true] Promotes BSON values to native types where possible, set to false to only receive wrapper types.
* @param {boolean} [options.promoteBuffers=false] Promotes Binary BSON values to native Node Buffers.
* @param {boolean} [options.bsonRegExp=false] By default, regex returned from MDB will be native to the language. Setting to true will ensure that a BSON.BSONRegExp object is returned.
* @param {(ReadPreference|string)} [options.readPreference] The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
* @param {boolean} [options.partial=false] Specify if the cursor should return partial results when querying against a sharded system
* @param {number} [options.maxTimeMS] Number of milliseconds to wait before aborting the query.
Expand Down Expand Up @@ -451,6 +456,8 @@ Collection.prototype.find = deprecateOptions(
newOptions.promoteValues = this.s.promoteValues;
if (newOptions.promoteBuffers == null && typeof this.s.promoteBuffers === 'boolean')
newOptions.promoteBuffers = this.s.promoteBuffers;
if (newOptions.bsonRegExp == null && typeof this.s.bsonRegExp === 'boolean')
newOptions.bsonRegExp = this.s.bsonRegExp;

// Sort options
if (findCommand.sort) {
Expand Down Expand Up @@ -1075,6 +1082,7 @@ Collection.prototype.save = deprecate(function(doc, options, callback) {
* @param {boolean} [options.promoteLongs=true] Promotes Long values to number if they fit inside the 53 bits resolution.
* @param {boolean} [options.promoteValues=true] Promotes BSON values to native types where possible, set to false to only receive wrapper types.
* @param {boolean} [options.promoteBuffers=false] Promotes Binary BSON values to native Node Buffers.
* @param {boolean} [options.bsonRegExp=false] By default, regex returned from MDB will be native to the language. Setting to true will ensure that a BSON.BSONRegExp object is returned.
* @param {(ReadPreference|string)} [options.readPreference] The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
* @param {boolean} [options.partial=false] Specify if the cursor should return partial results when querying against a sharded system
* @param {number} [options.maxTimeMS] Number of milliseconds to wait before aborting the query.
Expand Down Expand Up @@ -1899,6 +1907,7 @@ Collection.prototype.findAndRemove = deprecate(function(query, sort, options, ca
* @param {boolean} [options.promoteLongs=true] Promotes Long values to number if they fit inside the 53 bits resolution.
* @param {boolean} [options.promoteValues=true] Promotes BSON values to native types where possible, set to false to only receive wrapper types.
* @param {boolean} [options.promoteBuffers=false] Promotes Binary BSON values to native Node Buffers.
* @param {boolean} [options.bsonRegExp=false] By default, regex returned from MDB will be native to the language. Setting to true will ensure that a BSON.BSONRegExp object is returned.
* @param {object} [options.collation] Specify collation settings for operation. See {@link https://docs.mongodb.com/manual/reference/command/aggregate|aggregation documentation}.
* @param {string} [options.comment] Add a comment to an aggregation command
* @param {string|object} [options.hint] Add an index selection hint to an aggregation command
Expand Down
14 changes: 8 additions & 6 deletions lib/command_utils.js
Expand Up @@ -2,6 +2,7 @@
const Msg = require('./core/connection/msg').Msg;
const KillCursor = require('./core/connection/commands').KillCursor;
const GetMore = require('./core/connection/commands').GetMore;
const deepCopy = require('./utils').deepCopy;

/** Commands that we want to redact because of the sensitive nature of their contents */
const SENSITIVE_COMMANDS = new Set([
Expand Down Expand Up @@ -63,17 +64,17 @@ const extractCommand = command => {
let extractedCommand;
if (command instanceof GetMore) {
extractedCommand = {
getMore: command.cursorId,
getMore: deepCopy(command.cursorId),
collection: collectionName(command),
batchSize: command.numberToReturn
};
} else if (command instanceof KillCursor) {
extractedCommand = {
killCursors: collectionName(command),
cursors: command.cursorIds
cursors: deepCopy(command.cursorIds)
};
} else if (command instanceof Msg) {
extractedCommand = command.command;
extractedCommand = deepCopy(command.command);
} else if (command.query && command.query.$query) {
let result;
if (command.ns === 'admin.$cmd') {
Expand All @@ -84,12 +85,13 @@ const extractCommand = command => {
result = { find: collectionName(command) };
Object.keys(LEGACY_FIND_QUERY_MAP).forEach(key => {
if (typeof command.query[key] !== 'undefined')
result[LEGACY_FIND_QUERY_MAP[key]] = command.query[key];
result[LEGACY_FIND_QUERY_MAP[key]] = deepCopy(command.query[key]);
});
}

Object.keys(LEGACY_FIND_OPTIONS_MAP).forEach(key => {
if (typeof command[key] !== 'undefined') result[LEGACY_FIND_OPTIONS_MAP[key]] = command[key];
if (typeof command[key] !== 'undefined')
result[LEGACY_FIND_OPTIONS_MAP[key]] = deepCopy(command[key]);
});

OP_QUERY_KEYS.forEach(key => {
Expand All @@ -106,7 +108,7 @@ const extractCommand = command => {
extractedCommand = result;
}
} else {
extractedCommand = command.query || command;
extractedCommand = deepCopy(command.query || command);
}

const commandName = Object.keys(extractedCommand)[0];
Expand Down
13 changes: 11 additions & 2 deletions lib/core/connection/commands.js
Expand Up @@ -398,7 +398,12 @@ KillCursor.prototype.toBin = function() {
};

var Response = function(bson, message, msgHeader, msgBody, opts) {
opts = opts || { promoteLongs: true, promoteValues: true, promoteBuffers: false };
opts = opts || {
promoteLongs: true,
promoteValues: true,
promoteBuffers: false,
bsonRegExp: false
};
this.parsed = false;
this.raw = message;
this.data = msgBody;
Expand Down Expand Up @@ -429,6 +434,7 @@ var Response = function(bson, message, msgHeader, msgBody, opts) {
this.promoteLongs = typeof opts.promoteLongs === 'boolean' ? opts.promoteLongs : true;
this.promoteValues = typeof opts.promoteValues === 'boolean' ? opts.promoteValues : true;
this.promoteBuffers = typeof opts.promoteBuffers === 'boolean' ? opts.promoteBuffers : false;
this.bsonRegExp = typeof opts.bsonRegExp === 'boolean' ? opts.bsonRegExp : false;
};

Response.prototype.isParsed = function() {
Expand All @@ -449,13 +455,16 @@ Response.prototype.parse = function(options) {
typeof options.promoteValues === 'boolean' ? options.promoteValues : this.opts.promoteValues;
var promoteBuffers =
typeof options.promoteBuffers === 'boolean' ? options.promoteBuffers : this.opts.promoteBuffers;
var bsonRegExp =
typeof options.bsonRegExp === 'boolean' ? options.bsonRegExp : this.opts.bsonRegExp;
var bsonSize, _options;

// Set up the options
_options = {
promoteLongs: promoteLongs,
promoteValues: promoteValues,
promoteBuffers: promoteBuffers
promoteBuffers: promoteBuffers,
bsonRegExp: bsonRegExp
};

// Position within OP_REPLY at which documents start
Expand Down
3 changes: 3 additions & 0 deletions lib/core/connection/connect.js
Expand Up @@ -185,6 +185,9 @@ function prepareHandshakeDocument(authContext, callback) {
}

const authProvider = AUTH_PROVIDERS[credentials.mechanism];
if (authProvider == null) {
return callback(new MongoError(`No AuthProvider for ${credentials.mechanism} defined.`));
}
authProvider.prepare(handshakeDoc, authContext, callback);
return;
}
Expand Down
5 changes: 4 additions & 1 deletion lib/core/connection/connection.js
Expand Up @@ -38,6 +38,7 @@ const DEBUG_FIELDS = [
'promoteLongs',
'promoteValues',
'promoteBuffers',
'bsonRegExp',
'checkServerIdentity'
];

Expand Down Expand Up @@ -73,6 +74,7 @@ class Connection extends EventEmitter {
* @param {boolean} [options.promoteLongs] Convert Long values from the db into Numbers if they fit into 53 bits
* @param {boolean} [options.promoteValues] Promotes BSON values to native types where possible, set to false to only receive wrapper types.
* @param {boolean} [options.promoteBuffers] Promotes Binary BSON values to native Node Buffers.
* @param {boolean} [options.bsonRegExp] By default, regex returned from MDB will be native to the language. Setting to true will ensure that a BSON.BSONRegExp object is returned.
* @param {number} [options.maxBsonMessageSize=0x4000000] Largest possible size of a BSON message (for legacy purposes)
*/
constructor(socket, options) {
Expand Down Expand Up @@ -117,7 +119,8 @@ class Connection extends EventEmitter {
this.responseOptions = {
promoteLongs: typeof options.promoteLongs === 'boolean' ? options.promoteLongs : true,
promoteValues: typeof options.promoteValues === 'boolean' ? options.promoteValues : true,
promoteBuffers: typeof options.promoteBuffers === 'boolean' ? options.promoteBuffers : false
promoteBuffers: typeof options.promoteBuffers === 'boolean' ? options.promoteBuffers : false,
bsonRegExp: typeof options.bsonRegExp === 'boolean' ? options.bsonRegExp : false
};

// Flushing
Expand Down
13 changes: 11 additions & 2 deletions lib/core/connection/msg.js
Expand Up @@ -139,7 +139,12 @@ Msg.getRequestId = function() {

class BinMsg {
constructor(bson, message, msgHeader, msgBody, opts) {
opts = opts || { promoteLongs: true, promoteValues: true, promoteBuffers: false };
opts = opts || {
promoteLongs: true,
promoteValues: true,
promoteBuffers: false,
bsonRegExp: false
};
this.parsed = false;
this.raw = message;
this.data = msgBody;
Expand All @@ -161,6 +166,7 @@ class BinMsg {
this.promoteLongs = typeof opts.promoteLongs === 'boolean' ? opts.promoteLongs : true;
this.promoteValues = typeof opts.promoteValues === 'boolean' ? opts.promoteValues : true;
this.promoteBuffers = typeof opts.promoteBuffers === 'boolean' ? opts.promoteBuffers : false;
this.bsonRegExp = typeof opts.bsonRegExp === 'boolean' ? opts.bsonRegExp : false;

this.documents = [];
}
Expand All @@ -186,12 +192,15 @@ class BinMsg {
typeof options.promoteBuffers === 'boolean'
? options.promoteBuffers
: this.opts.promoteBuffers;
const bsonRegExp =
typeof options.bsonRegExp === 'boolean' ? options.bsonRegExp : this.opts.bsonRegExp;

// Set up the options
const _options = {
promoteLongs: promoteLongs,
promoteValues: promoteValues,
promoteBuffers: promoteBuffers
promoteBuffers: promoteBuffers,
bsonRegExp: bsonRegExp
};

while (this.index < this.data.length) {
Expand Down
4 changes: 4 additions & 0 deletions lib/core/connection/pool.js
Expand Up @@ -76,6 +76,7 @@ var _id = 0;
* @param {boolean} [options.promoteLongs=true] Convert Long values from the db into Numbers if they fit into 53 bits
* @param {boolean} [options.promoteValues=true] Promotes BSON values to native types where possible, set to false to only receive wrapper types.
* @param {boolean} [options.promoteBuffers=false] Promotes Binary BSON values to native Node Buffers.
* @param {boolean} [options.bsonRegExp=false] By default, regex returned from MDB will be native to the language. Setting to true will ensure that a BSON.BSONRegExp object is returned.
* @param {boolean} [options.domainsEnabled=false] Enable the wrapping of the callback in the current domain, disabled by default to avoid perf hit.
* @fires Pool#connect
* @fires Pool#close
Expand Down Expand Up @@ -127,6 +128,7 @@ var Pool = function(topology, options) {
promoteLongs: true,
promoteValues: true,
promoteBuffers: false,
bsonRegExp: false,
// Reconnection options
reconnect: true,
reconnectInterval: 1000,
Expand Down Expand Up @@ -870,6 +872,7 @@ Pool.prototype.write = function(command, options, cb) {
promoteLongs: true,
promoteValues: true,
promoteBuffers: false,
bsonRegExp: false,
fullResult: false
};

Expand All @@ -879,6 +882,7 @@ Pool.prototype.write = function(command, options, cb) {
typeof options.promoteValues === 'boolean' ? options.promoteValues : true;
operation.promoteBuffers =
typeof options.promoteBuffers === 'boolean' ? options.promoteBuffers : false;
operation.bsonRegExp = typeof options.bsonRegExp === 'boolean' ? options.bsonRegExp : false;
operation.raw = typeof options.raw === 'boolean' ? options.raw : false;
operation.immediateRelease =
typeof options.immediateRelease === 'boolean' ? options.immediateRelease : false;
Expand Down
7 changes: 7 additions & 0 deletions lib/core/cursor.js
Expand Up @@ -146,6 +146,13 @@ class CoreCursor extends Readable {
this.cursorState.promoteBuffers = options.promoteBuffers;
}

// Add bsonRegExp to cursor state
if (typeof topologyOptions.bsonRegExp === 'boolean') {
this.cursorState.bsonRegExp = topologyOptions.bsonRegExp;
} else if (typeof options.bsonRegExp === 'boolean') {
this.cursorState.bsonRegExp = options.bsonRegExp;
}

if (topologyOptions.reconnect) {
this.cursorState.reconnect = topologyOptions.reconnect;
}
Expand Down
3 changes: 2 additions & 1 deletion lib/core/sdam/monitor.js
Expand Up @@ -85,7 +85,8 @@ class Monitor extends EventEmitter {
raw: false,
promoteLongs: true,
promoteValues: true,
promoteBuffers: true
promoteBuffers: true,
bsonRegExp: true
}
);

Expand Down
5 changes: 5 additions & 0 deletions lib/core/sdam/server.js
Expand Up @@ -50,6 +50,7 @@ const DEBUG_FIELDS = [
'promoteLongs',
'promoteValues',
'promoteBuffers',
'bsonRegExp',
'servername'
];

Expand Down Expand Up @@ -168,6 +169,10 @@ class Server extends EventEmitter {
return this.s.description;
}

get supportsRetryableWrites() {
return supportsRetryableWrites(this);
}

get name() {
return this.s.description.address;
}
Expand Down
38 changes: 24 additions & 14 deletions lib/core/sdam/topology.js
Expand Up @@ -9,7 +9,6 @@ const events = require('./events');
const Server = require('./server').Server;
const relayEvents = require('../utils').relayEvents;
const ReadPreference = require('../topologies/read_preference');
const isRetryableWritesSupported = require('../topologies/shared').isRetryableWritesSupported;
const CoreCursor = require('../cursor').CoreCursor;
const deprecate = require('util').deprecate;
const BSON = require('../connection/utils').retrieveBSON();
Expand Down Expand Up @@ -674,12 +673,17 @@ class Topology extends EventEmitter {
return;
}

const notAlreadyRetrying = !options.retrying;
const retryWrites = !!options.retryWrites;
const hasSession = !!options.session;
const supportsRetryableWrites = server.supportsRetryableWrites;
const notInTransaction = !hasSession || !options.session.inTransaction();
const willRetryWrite =
!options.retrying &&
!!options.retryWrites &&
options.session &&
isRetryableWritesSupported(this) &&
!options.session.inTransaction() &&
notAlreadyRetrying &&
retryWrites &&
hasSession &&
supportsRetryableWrites &&
notInTransaction &&
isWriteCommand(cmd);

const cb = (err, result) => {
Expand Down Expand Up @@ -930,20 +934,26 @@ function executeWriteOperation(args, options, callback) {
const ns = args.ns;
const ops = args.ops;

const willRetryWrite =
!args.retrying &&
!!options.retryWrites &&
options.session &&
isRetryableWritesSupported(topology) &&
!options.session.inTransaction() &&
options.explain === undefined;

topology.selectServer(writableServerSelector(), options, (err, server) => {
if (err) {
callback(err, null);
return;
}

const notAlreadyRetrying = !args.retrying;
const retryWrites = !!options.retryWrites;
const hasSession = !!options.session;
const supportsRetryableWrites = server.supportsRetryableWrites;
const notInTransaction = !hasSession || !options.session.inTransaction();
const notExplaining = options.explain === undefined;
const willRetryWrite =
notAlreadyRetrying &&
retryWrites &&
hasSession &&
supportsRetryableWrites &&
notInTransaction &&
notExplaining;

const handler = (err, result) => {
if (!err) return callback(null, result);
if (!shouldRetryOperation(err)) {
Expand Down
1 change: 1 addition & 0 deletions lib/core/topologies/mongos.js
Expand Up @@ -88,6 +88,7 @@ var handlers = ['connect', 'close', 'error', 'timeout', 'parseError'];
* @param {boolean} [options.promoteLongs=true] Convert Long values from the db into Numbers if they fit into 53 bits
* @param {boolean} [options.promoteValues=true] Promotes BSON values to native types where possible, set to false to only receive wrapper types.
* @param {boolean} [options.promoteBuffers=false] Promotes Binary BSON values to native Node Buffers.
* @param {boolean} [options.bsonRegExp=false] By default, regex returned from MDB will be native to the language. Setting to true will ensure that a BSON.BSONRegExp object is returned.
* @param {boolean} [options.domainsEnabled=false] Enable the wrapping of the callback in the current domain, disabled by default to avoid perf hit.
* @param {boolean} [options.monitorCommands=false] Enable command monitoring for this topology
* @return {Mongos} A cursor instance
Expand Down

0 comments on commit 91a2fc9

Please sign in to comment.