Skip to content

Commit

Permalink
NODE-606 better error handling on destroyed topology for db.js methods.
Browse files Browse the repository at this point in the history
  • Loading branch information
christkv committed Nov 16, 2015
1 parent f565832 commit 9942ced
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 0 deletions.
1 change: 1 addition & 0 deletions HISTORY.md
Expand Up @@ -6,6 +6,7 @@
* NODE-601 Added maxAwaitTimeMS support for 3.2 getMore to allow for custom timeouts on tailable cursors.
* Updated mongodb-core to 1.2.22.
* Return destination in GridStore pipe function.
* NODE-606 better error handling on destroyed topology for db.js methods.

2.0.48 11-07-2015
-----------------
Expand Down
39 changes: 39 additions & 0 deletions lib/db.js
Expand Up @@ -259,6 +259,9 @@ define.classMethod('open', {callback: true, promise:true});
*/

var executeCommand = function(self, command, options, callback) {
// Did the user destroy the topology
if(self.serverConfig && self.serverConfig.isDestroyed()) return callback(new MongoError('topology was destroyed'));
// Get the db name we are executing against
var dbName = options.dbName || options.authdb || self.s.databaseName;
// If we have a readPreference set
if(options.readPreference == null && self.s.readPreference) {
Expand Down Expand Up @@ -452,6 +455,8 @@ define.classMethod('collection', {callback: true, promise:false, returns: [Colle
var createCollection = function(self, name, options, callback) {
// Get the write concern options
var finalOptions = writeConcern(shallowClone(options), self, options);
// Did the user destroy the topology
if(self.serverConfig && self.serverConfig.isDestroyed()) return callback(new MongoError('topology was destroyed'));

// Check if we have the name
self.listCollections({name: name}).toArray(function(err, collections) {
Expand Down Expand Up @@ -635,6 +640,9 @@ var evaluate = function(self, code, parameters, options, callback) {
var finalCode = code;
var finalParameters = [];

// Did the user destroy the topology
if(self.serverConfig && self.serverConfig.isDestroyed()) return callback(new MongoError('topology was destroyed'));

// If not a code object translate to one
if(!(finalCode instanceof Code)) finalCode = new Code(finalCode);
// Ensure the parameters are correct
Expand Down Expand Up @@ -746,6 +754,8 @@ Db.prototype.dropCollection = function(name, callback) {

// Check if the callback is in fact a string
if(typeof callback == 'function') return this.command(cmd, this.s.options, function(err, result) {
// Did the user destroy the topology
if(self.serverConfig && self.serverConfig.isDestroyed()) return callback(new MongoError('topology was destroyed'));
if(err) return handleCallback(callback, err);
if(result.ok) return handleCallback(callback, null, true);
handleCallback(callback, null, false);
Expand All @@ -755,6 +765,8 @@ Db.prototype.dropCollection = function(name, callback) {
return new this.s.promiseLibrary(function(resolve, reject) {
// Execute command
self.command(cmd, self.s.options, function(err, result) {
// Did the user destroy the topology
if(self.serverConfig && self.serverConfig.isDestroyed()) return reject(new MongoError('topology was destroyed'));
if(err) return reject(err);
if(result.ok) return resolve(true);
resolve(false);
Expand All @@ -778,6 +790,8 @@ Db.prototype.dropDatabase = function(callback) {

// Check if the callback is in fact a string
if(typeof callback == 'function') return this.command(cmd, this.s.options, function(err, result) {
// Did the user destroy the topology
if(self.serverConfig && self.serverConfig.isDestroyed()) return callback(new MongoError('topology was destroyed'));
if(callback == null) return;
if(err) return handleCallback(callback, err, null);
handleCallback(callback, null, result.ok ? true : false);
Expand All @@ -787,6 +801,8 @@ Db.prototype.dropDatabase = function(callback) {
return new this.s.promiseLibrary(function(resolve, reject) {
// Execute command
self.command(cmd, self.s.options, function(err, result) {
// Did the user destroy the topology
if(self.serverConfig && self.serverConfig.isDestroyed()) return reject(new MongoError('topology was destroyed'));
if(err) return reject(err);
if(result.ok) return resolve(true);
resolve(false);
Expand Down Expand Up @@ -862,13 +878,17 @@ Db.prototype.executeDbAdminCommand = function(selector, options, callback) {

// Return the callback
if(typeof callback == 'function') return self.s.topology.command('admin.$cmd', selector, options, function(err, result) {
// Did the user destroy the topology
if(self.serverConfig && self.serverConfig.isDestroyed()) return callback(new MongoError('topology was destroyed'));
if(err) return handleCallback(callback, err);
handleCallback(callback, null, result.result);
});

// Return promise
return new self.s.promiseLibrary(function(resolve, reject) {
self.s.topology.command('admin.$cmd', selector, options, function(err, result) {
// Did the user destroy the topology
if(self.serverConfig && self.serverConfig.isDestroyed()) return reject(new MongoError('topology was destroyed'));
if(err) return reject(err);
resolve(result.result);
});
Expand Down Expand Up @@ -930,6 +950,9 @@ var createIndex = function(self, name, fieldOrSpec, options, callback) {
throw MongoError.create({message: "Cannot use a writeConcern without a provided callback", driver:true});
}

// Did the user destroy the topology
if(self.serverConfig && self.serverConfig.isDestroyed()) return callback(new MongoError('topology was destroyed'));

// Attempt to run using createIndexes command
createIndexUsingCreateIndexes(self, name, fieldOrSpec, options, function(err, result) {
if(err == null) return handleCallback(callback, err, result);
Expand Down Expand Up @@ -996,6 +1019,9 @@ var ensureIndex = function(self, name, fieldOrSpec, options, callback) {
var selector = createCreateIndexCommand(self, name, fieldOrSpec, options);
var index_name = selector.name;

// Did the user destroy the topology
if(self.serverConfig && self.serverConfig.isDestroyed()) return callback(new MongoError('topology was destroyed'));

// Default command options
var commandOptions = {};
// Check if the index allready exists
Expand Down Expand Up @@ -1144,6 +1170,8 @@ var _executeAuthCreateUserCommand = function(self, username, password, options,
}

var addUser = function(self, username, password, options, callback) {
// Did the user destroy the topology
if(self.serverConfig && self.serverConfig.isDestroyed()) return callback(new MongoError('topology was destroyed'));
// Attempt to execute auth command
_executeAuthCreateUserCommand(self, username, password, options, function(err, r) {
// We need to perform the backward compatible insert operation
Expand Down Expand Up @@ -1227,6 +1255,8 @@ define.classMethod('addUser', {callback: true, promise:true});

var _executeAuthRemoveUserCommand = function(self, username, options, callback) {
if(typeof options == 'function') callback = options, options = {};
// Did the user destroy the topology
if(self.serverConfig && self.serverConfig.isDestroyed()) return callback(new MongoError('topology was destroyed'));
// Get the error options
var commandOptions = {writeCommand:true};
if(options['dbName']) commandOptions.dbName = options['dbName'];
Expand Down Expand Up @@ -1317,6 +1347,8 @@ Db.prototype.removeUser = function(username, options, callback) {
};

var authenticate = function(self, username, password, options, callback) {
// Did the user destroy the topology
if(self.serverConfig && self.serverConfig.isDestroyed()) return callback(new MongoError('topology was destroyed'));
// the default db to authenticate against is 'self'
// if authententicate is called from a retry context, it may be another one, like admin
var authdb = options.authdb ? options.authdb : options.dbName;
Expand Down Expand Up @@ -1456,13 +1488,17 @@ Db.prototype.logout = function(options, callback) {

// Execute the command
if(typeof callback == 'function') return this.command(cmd, options, function(err, result) {
// Did the user destroy the topology
if(self.serverConfig && self.serverConfig.isDestroyed()) return callback(new MongoError('topology was destroyed'));
if(err) return handleCallback(callback, err, false);
handleCallback(callback, null, true)
});

// Return promise
return new this.s.promiseLibrary(function(resolve, reject) {
self.command(cmd, options, function(err, result) {
// Did the user destroy the topology
if(self.serverConfig && self.serverConfig.isDestroyed()) return reject(new MongoError('topology was destroyed'));
if(err) return reject(err);
resolve(true);
});
Expand Down Expand Up @@ -1509,6 +1545,9 @@ var indexInformation = function(self, name, options, callback) {
// If we specified full information
var full = options['full'] == null ? false : options['full'];

// Did the user destroy the topology
if(self.serverConfig && self.serverConfig.isDestroyed()) return callback(new MongoError('topology was destroyed'));

// Process all the results from the index command and collection
var processResults = function(indexes) {
// Contains all the information
Expand Down
4 changes: 4 additions & 0 deletions lib/server.js
Expand Up @@ -345,6 +345,10 @@ Server.prototype.isConnected = function() {
return this.s.server.isConnected();
}

Server.prototype.isDestroyed = function() {
return this.s.server.isDestroyed();
}

define.classMethod('isConnected', {callback: false, promise:false, returns: [Boolean]});

// Insert
Expand Down
20 changes: 20 additions & 0 deletions test/functional/index_tests.js
Expand Up @@ -818,6 +818,26 @@ exports['should correctly pass partialIndexes through to createIndexCommand'] =
}
}

/**
* @ignore
*/
exports['should correctly error out due to driver close'] = {
metadata: { requires: { topology: ['single'] } },

// The actual test we wish to run
test: function(configuration, test) {
var db = configuration.newDbInstance(configuration.writeConcernMax(), {poolSize:1});
db.open(function(err, db) {
db.close(function() {
db.createCollection('nonexisting', {w:1}, function(err, collection) {
test.ok(err != null);
test.done();
});
});
});
}
}

// /**
// * @ignore
// */
Expand Down

0 comments on commit 9942ced

Please sign in to comment.