mongodb-core
Advanced tools
Comparing version 3.2.0-beta1 to 3.2.0-beta2
@@ -48,4 +48,4 @@ 'use strict'; | ||
this.password = options.password; | ||
this.source = options.source; | ||
this.mechanism = options.mechanism; | ||
this.source = options.source || options.db; | ||
this.mechanism = options.mechanism || 'default'; | ||
this.mechanismProperties = options.mechanismProperties; | ||
@@ -52,0 +52,0 @@ } |
@@ -237,2 +237,5 @@ 'use strict'; | ||
socket = tls.connect(parseSslOptions(family, options)); | ||
if (typeof socket.disableRenegotiation === 'function') { | ||
socket.disableRenegotiation(); | ||
} | ||
} else { | ||
@@ -239,0 +242,0 @@ socket = net.createConnection(parseConnectOptions(family, options)); |
@@ -10,3 +10,2 @@ 'use strict'; | ||
const f = require('util').format; | ||
const Query = require('./commands').Query; | ||
const Msg = require('./msg').Msg; | ||
@@ -20,6 +19,6 @@ const CommandResult = require('./command_result'); | ||
const uncompressibleCommands = require('../wireprotocol/compression').uncompressibleCommands; | ||
const resolveClusterTime = require('../topologies/shared').resolveClusterTime; | ||
const apm = require('./apm'); | ||
const Buffer = require('safe-buffer').Buffer; | ||
const connect = require('./connect'); | ||
const updateSessionFromResponse = require('../sessions').updateSessionFromResponse; | ||
@@ -34,11 +33,2 @@ var DISCONNECTED = 'disconnected'; | ||
function hasSessionSupport(topology) { | ||
if (topology == null) return false; | ||
if (topology.description) { | ||
return topology.description.maxWireVersion >= 6; | ||
} | ||
return topology.ismaster == null ? false : topology.ismaster.maxWireVersion >= 6; | ||
} | ||
/** | ||
@@ -434,22 +424,12 @@ * Creates a new Pool instance | ||
// Look for clusterTime, operationTime, and recoveryToken and update them if necessary | ||
if (message.documents[0]) { | ||
const document = message.documents[0]; | ||
const session = workItem.session; | ||
const document = message.documents[0]; | ||
if (document.$clusterTime) { | ||
const $clusterTime = document.$clusterTime; | ||
self.topology.clusterTime = $clusterTime; | ||
if (session != null) { | ||
resolveClusterTime(session, $clusterTime); | ||
} | ||
if (session) { | ||
updateSessionFromResponse(session, document); | ||
} | ||
if (document.operationTime && session && session.supports.causalConsistency) { | ||
session.advanceOperationTime(message.documents[0].operationTime); | ||
if (document.$clusterTime) { | ||
self.topology.clusterTime = document.$clusterTime; | ||
} | ||
if (document.recoveryToken && session && session.inTransaction()) { | ||
session.transaction._recoveryToken = document.recoveryToken; | ||
} | ||
} | ||
@@ -460,13 +440,11 @@ | ||
const responseDoc = message.documents[0]; | ||
if (responseDoc.ok === 0 || responseDoc.$err || responseDoc.errmsg || responseDoc.code) { | ||
return handleOperationCallback(self, workItem.cb, new MongoError(responseDoc)); | ||
} | ||
if (responseDoc.writeConcernError) { | ||
const err = | ||
responseDoc.ok === 1 | ||
? new MongoWriteConcernError(responseDoc.writeConcernError, responseDoc) | ||
: new MongoWriteConcernError(responseDoc.writeConcernError); | ||
const err = new MongoWriteConcernError(responseDoc.writeConcernError, responseDoc); | ||
return handleOperationCallback(self, workItem.cb, err); | ||
} | ||
if (responseDoc.ok === 0 || responseDoc.$err || responseDoc.errmsg || responseDoc.code) { | ||
return handleOperationCallback(self, workItem.cb, new MongoError(responseDoc)); | ||
} | ||
} | ||
@@ -637,3 +615,3 @@ | ||
Pool.prototype.auth = function(credentials, callback) { | ||
callback(null, null); | ||
if (typeof callback === 'function') callback(null, null); | ||
}; | ||
@@ -646,3 +624,3 @@ | ||
Pool.prototype.logout = function(dbName, callback) { | ||
callback(null, null); | ||
if (typeof callback === 'function') callback(null, null); | ||
}; | ||
@@ -908,50 +886,2 @@ | ||
if (hasSessionSupport(this.topology)) { | ||
let sessionOptions = {}; | ||
if (this.topology.clusterTime) { | ||
sessionOptions = { $clusterTime: this.topology.clusterTime }; | ||
} | ||
if (operation.session) { | ||
// TODO: reenable when sessions development is complete | ||
// if (operation.session.topology !== this.topology) { | ||
// return cb( | ||
// new MongoError('Sessions may only be used with the client they were created from') | ||
// ); | ||
// } | ||
if (operation.session.hasEnded) { | ||
return cb(new MongoError('Use of expired sessions is not permitted')); | ||
} | ||
if ( | ||
operation.session.clusterTime && | ||
operation.session.clusterTime.clusterTime.greaterThan( | ||
sessionOptions.$clusterTime.clusterTime | ||
) | ||
) { | ||
sessionOptions.$clusterTime = operation.session.clusterTime; | ||
} | ||
sessionOptions.lsid = operation.session.id; | ||
// update the `lastUse` of the acquired ServerSession | ||
operation.session.serverSession.lastUse = Date.now(); | ||
} | ||
// decorate the commands with session-specific details | ||
let commandDocument = command; | ||
if (command instanceof Query) { | ||
commandDocument = command.query; | ||
} else if (command instanceof Msg) { | ||
commandDocument = command.command; | ||
} | ||
if (commandDocument.$query) { | ||
commandDocument = commandDocument.$query; | ||
} | ||
Object.assign(commandDocument, sessionOptions); | ||
} | ||
// If command monitoring is enabled we need to modify the callback here | ||
@@ -958,0 +888,0 @@ if (self.options.monitorCommands) { |
@@ -94,2 +94,15 @@ 'use strict'; | ||
function makeWriteConcernResultObject(input) { | ||
const output = Object.assign({}, input); | ||
if (output.ok === 0) { | ||
output.ok = 1; | ||
delete output.errmsg; | ||
delete output.code; | ||
delete output.codeName; | ||
} | ||
return output; | ||
} | ||
/** | ||
@@ -109,3 +122,3 @@ * An error thrown when the server reports a writeConcernError | ||
if (result != null) { | ||
this.result = result; | ||
this.result = makeWriteConcernResultObject(result); | ||
} | ||
@@ -112,0 +125,0 @@ } |
@@ -15,2 +15,5 @@ 'use strict'; | ||
const isPromiseLike = require('./utils').isPromiseLike; | ||
const ReadPreference = require('./topologies/read_preference'); | ||
const isTransactionCommand = require('./transactions').isTransactionCommand; | ||
const resolveClusterTime = require('./topologies/shared').resolveClusterTime; | ||
@@ -129,2 +132,3 @@ function assertAlive(session, callback) { | ||
this.sessionPool.release(this.serverSession); | ||
this.serverSession = null; | ||
@@ -474,3 +478,3 @@ // spec indicates that we should ignore all errors for `endSessions` | ||
if (session.transaction.recoveryToken) { | ||
if (commandName === 'commitTransaction' && session.transaction.recoveryToken) { | ||
command.recoveryToken = session.transaction.recoveryToken; | ||
@@ -601,2 +605,86 @@ } | ||
/** | ||
* Optionally decorate a command with sessions specific keys | ||
* | ||
* @param {ClientSession} session the session tracking transaction state | ||
* @param {Object} command the command to decorate | ||
* @param {Object} topology the topology for tracking the cluster time | ||
* @param {Object} [options] Optional settings passed to calling operation | ||
* @return {MongoError|null} An error, if some error condition was met | ||
*/ | ||
function applySession(session, command, options) { | ||
const serverSession = session.serverSession; | ||
if (serverSession == null) { | ||
// TODO: merge this with `assertAlive`, did not want to throw a try/catch here | ||
return new MongoError('Cannot use a session that has ended'); | ||
} | ||
// mark the last use of this session, and apply the `lsid` | ||
serverSession.lastUse = Date.now(); | ||
command.lsid = serverSession.id; | ||
// first apply non-transaction-specific sessions data | ||
const inTransaction = session.inTransaction() || isTransactionCommand(command); | ||
const isRetryableWrite = options.willRetryWrite; | ||
if (serverSession.txnNumber && (isRetryableWrite || inTransaction)) { | ||
command.txnNumber = BSON.Long.fromNumber(serverSession.txnNumber); | ||
} | ||
// now attempt to apply transaction-specific sessions data | ||
if (!inTransaction) { | ||
if (session.transaction.state !== TxnState.NO_TRANSACTION) { | ||
session.transaction.transition(TxnState.NO_TRANSACTION); | ||
} | ||
// TODO: the following should only be applied to read operation per spec. | ||
// for causal consistency | ||
if (session.supports.causalConsistency && session.operationTime) { | ||
command.readConcern = command.readConcern || {}; | ||
Object.assign(command.readConcern, { afterClusterTime: session.operationTime }); | ||
} | ||
return; | ||
} | ||
if (options.readPreference && !options.readPreference.equals(ReadPreference.primary)) { | ||
return new MongoError( | ||
`Read preference in a transaction must be primary, not: ${options.readPreference.mode}` | ||
); | ||
} | ||
// `autocommit` must always be false to differentiate from retryable writes | ||
command.autocommit = false; | ||
if (session.transaction.state === TxnState.STARTING_TRANSACTION) { | ||
session.transaction.transition(TxnState.TRANSACTION_IN_PROGRESS); | ||
command.startTransaction = true; | ||
const readConcern = | ||
session.transaction.options.readConcern || session.clientOptions.readConcern; | ||
if (readConcern) { | ||
command.readConcern = readConcern; | ||
} | ||
if (session.supports.causalConsistency && session.operationTime) { | ||
command.readConcern = command.readConcern || {}; | ||
Object.assign(command.readConcern, { afterClusterTime: session.operationTime }); | ||
} | ||
} | ||
} | ||
function updateSessionFromResponse(session, document) { | ||
if (document.$clusterTime) { | ||
resolveClusterTime(session, document.$clusterTime); | ||
} | ||
if (document.operationTime && session && session.supports.causalConsistency) { | ||
session.advanceOperationTime(document.operationTime); | ||
} | ||
if (document.recoveryToken && session && session.inTransaction()) { | ||
session.transaction._recoveryToken = document.recoveryToken; | ||
} | ||
} | ||
module.exports = { | ||
@@ -606,3 +694,5 @@ ClientSession, | ||
ServerSessionPool, | ||
TxnState | ||
TxnState, | ||
applySession, | ||
updateSessionFromResponse | ||
}; |
@@ -303,3 +303,3 @@ 'use strict'; | ||
Mongos.prototype.auth = function(credentials, callback) { | ||
callback(null, null); | ||
if (typeof callback === 'function') callback(null, null); | ||
}; | ||
@@ -306,0 +306,0 @@ |
@@ -943,3 +943,3 @@ 'use strict'; | ||
ReplSet.prototype.auth = function(credentials, callback) { | ||
callback(null, null); | ||
if (typeof callback === 'function') callback(null, null); | ||
}; | ||
@@ -946,0 +946,0 @@ |
@@ -508,3 +508,3 @@ 'use strict'; | ||
Server.prototype.auth = function(credentials, callback) { | ||
callback(null, null); | ||
if (typeof callback === 'function') callback(null, null); | ||
}; | ||
@@ -511,0 +511,0 @@ |
@@ -118,2 +118,6 @@ 'use strict'; | ||
get isPinned() { | ||
return !!this.server; | ||
} | ||
/** | ||
@@ -160,2 +164,6 @@ * @ignore | ||
module.exports = { TxnState, Transaction }; | ||
function isTransactionCommand(command) { | ||
return !!(command.commitTransaction || command.abortTransaction); | ||
} | ||
module.exports = { TxnState, Transaction, isTransactionCommand }; |
@@ -5,10 +5,8 @@ 'use strict'; | ||
const Msg = require('../connection/msg').Msg; | ||
const retrieveBSON = require('../connection/utils').retrieveBSON; | ||
const MongoError = require('../error').MongoError; | ||
const getReadPreference = require('./shared').getReadPreference; | ||
const BSON = retrieveBSON(); | ||
const ReadPreference = require('../topologies/read_preference'); | ||
const TxnState = require('../transactions').TxnState; | ||
const isSharded = require('./shared').isSharded; | ||
const databaseNamespace = require('./shared').databaseNamespace; | ||
const isTransactionCommand = require('../transactions').isTransactionCommand; | ||
const applySession = require('../sessions').applySession; | ||
@@ -29,3 +27,23 @@ function command(server, ns, cmd, options, callback) { | ||
let clusterTime = server.clusterTime; | ||
let finalCmd = Object.assign({}, cmd); | ||
if (hasSessionSupport(server) && session) { | ||
if ( | ||
session.clusterTime && | ||
session.clusterTime.clusterTime.greaterThan(clusterTime.clusterTime) | ||
) { | ||
clusterTime = session.clusterTime; | ||
} | ||
const err = applySession(session, finalCmd, options); | ||
if (err) { | ||
return callback(err); | ||
} | ||
} | ||
// if we have a known cluster time, gossip it | ||
if (clusterTime) { | ||
finalCmd.$clusterTime = clusterTime; | ||
} | ||
if ( | ||
@@ -43,7 +61,2 @@ isSharded(server) && | ||
const err = decorateWithSessionsData(finalCmd, session, options); | ||
if (err) { | ||
return callback(err); | ||
} | ||
const commandOptions = Object.assign( | ||
@@ -90,2 +103,11 @@ { | ||
function hasSessionSupport(topology) { | ||
if (topology == null) return false; | ||
if (topology.description) { | ||
return topology.description.maxWireVersion >= 6; | ||
} | ||
return topology.ismaster == null ? false : topology.ismaster.maxWireVersion >= 6; | ||
} | ||
function supportsOpMsg(topologyOrServer) { | ||
@@ -103,69 +125,2 @@ const description = topologyOrServer.ismaster | ||
function isTransactionCommand(command) { | ||
return !!(command.commitTransaction || command.abortTransaction); | ||
} | ||
/** | ||
* Optionally decorate a command with sessions specific keys | ||
* | ||
* @param {Object} command the command to decorate | ||
* @param {ClientSession} session the session tracking transaction state | ||
* @param {Object} [options] Optional settings passed to calling operation | ||
* @return {MongoError|null} An error, if some error condition was met | ||
*/ | ||
function decorateWithSessionsData(command, session, options) { | ||
if (!session) { | ||
return; | ||
} | ||
// first apply non-transaction-specific sessions data | ||
const serverSession = session.serverSession; | ||
const inTransaction = session.inTransaction() || isTransactionCommand(command); | ||
const isRetryableWrite = options.willRetryWrite; | ||
if (serverSession.txnNumber && (isRetryableWrite || inTransaction)) { | ||
command.txnNumber = BSON.Long.fromNumber(serverSession.txnNumber); | ||
} | ||
// now attempt to apply transaction-specific sessions data | ||
if (!inTransaction) { | ||
if (session.transaction.state !== TxnState.NO_TRANSACTION) { | ||
session.transaction.transition(TxnState.NO_TRANSACTION); | ||
} | ||
// for causal consistency | ||
if (session.supports.causalConsistency && session.operationTime) { | ||
command.readConcern = command.readConcern || {}; | ||
Object.assign(command.readConcern, { afterClusterTime: session.operationTime }); | ||
} | ||
return; | ||
} | ||
if (options.readPreference && !options.readPreference.equals(ReadPreference.primary)) { | ||
return new MongoError( | ||
`Read preference in a transaction must be primary, not: ${options.readPreference.mode}` | ||
); | ||
} | ||
// `autocommit` must always be false to differentiate from retryable writes | ||
command.autocommit = false; | ||
if (session.transaction.state === TxnState.STARTING_TRANSACTION) { | ||
session.transaction.transition(TxnState.TRANSACTION_IN_PROGRESS); | ||
command.startTransaction = true; | ||
const readConcern = | ||
session.transaction.options.readConcern || session.clientOptions.readConcern; | ||
if (readConcern) { | ||
command.readConcern = readConcern; | ||
} | ||
if (session.supports.causalConsistency && session.operationTime) { | ||
command.readConcern = command.readConcern || {}; | ||
Object.assign(command.readConcern, { afterClusterTime: session.operationTime }); | ||
} | ||
} | ||
} | ||
module.exports = command; |
{ | ||
"name": "mongodb-core", | ||
"version": "3.2.0-beta1", | ||
"version": "3.2.0-beta2", | ||
"description": "Core MongoDB driver functionality, no bells and whistles and meant for integration not end applications", | ||
@@ -28,3 +28,3 @@ "main": "index.js", | ||
"dependencies": { | ||
"bson": "^1.1.0", | ||
"bson": "^1.1.1", | ||
"require_optional": "^1.0.1", | ||
@@ -34,3 +34,3 @@ "safe-buffer": "^5.1.2" | ||
"devDependencies": { | ||
"chai": "^4.1.2", | ||
"chai": "^4.2.0", | ||
"chai-subset": "^1.6.0", | ||
@@ -43,3 +43,3 @@ "co": "^4.6.0", | ||
"mongodb-mock-server": "^1.0.1", | ||
"mongodb-test-runner": "^1.1.18", | ||
"mongodb-test-runner": "^1.3.4", | ||
"prettier": "~1.12.0", | ||
@@ -46,0 +46,0 @@ "sinon": "^6.0.0", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
556050
13663
Updatedbson@^1.1.1