Skip to content

Commit

Permalink
refactor(db)!: suppress Db events (#2251)
Browse files Browse the repository at this point in the history
Db class no longer emits events, only MongoClient does now. Also removed parent/child relationships for databases.

NODE-1709
  • Loading branch information
emadum committed Mar 10, 2020
1 parent 77442f8 commit eed1131
Show file tree
Hide file tree
Showing 6 changed files with 11 additions and 185 deletions.
93 changes: 1 addition & 92 deletions lib/db.js
@@ -1,7 +1,6 @@
'use strict';

const EventEmitter = require('events');
const { inherits, deprecate } = require('util');
const { deprecate } = require('util');
const { AggregationCursor, CommandCursor } = require('./cursor');
const { ObjectID } = require('./utils').retrieveBSON();
const ReadPreference = require('./read_preference');
Expand All @@ -26,7 +25,6 @@ const {

// Operations
const {
createListener,
ensureIndex,
evaluate,
profilingInfo,
Expand Down Expand Up @@ -88,7 +86,6 @@ const legalOptionNames = [
'readConcern',
'retryMiliSeconds',
'numberOfRetries',
'parentDb',
'noListener',
'loggerLevel',
'logger',
Expand Down Expand Up @@ -130,18 +127,11 @@ const legalOptionNames = [
* @property {boolean} slaveOk The current slaveOk value for the db instance.
* @property {object} writeConcern The current write concern values.
* @property {object} topology Access the topology object (single server, replicaset or mongos).
* @fires Db#close
* @fires Db#reconnect
* @fires Db#error
* @fires Db#timeout
* @fires Db#parseError
* @fires Db#fullsetup
* @return {Db} a Db instance.
*/
function Db(databaseName, topology, options) {
options = options || {};
if (!(this instanceof Db)) return new Db(databaseName, topology, options);
EventEmitter.call(this);

// Get the promiseLibrary
const promiseLibrary = options.promiseLibrary || Promise;
Expand All @@ -156,8 +146,6 @@ function Db(databaseName, topology, options) {
this.s = {
// DbCache
dbCache: {},
// Children db's
children: [],
// Topology
topology: topology,
// Options
Expand All @@ -170,8 +158,6 @@ function Db(databaseName, topology, options) {
readPreference: ReadPreference.fromOptions(options),
// Set buffermaxEntries
bufferMaxEntries: typeof options.bufferMaxEntries === 'number' ? options.bufferMaxEntries : -1,
// Parent db (if chained)
parentDb: options.parentDb || null,
// Set up the primary key factory or fallback to ObjectID
pkFactory: options.pkFactory || ObjectID,
// Get native parser
Expand All @@ -195,23 +181,9 @@ function Db(databaseName, topology, options) {
getSingleProperty(this, 'bufferMaxEntries', this.s.bufferMaxEntries);
getSingleProperty(this, 'databaseName', this.s.namespace.db);

// This is a child db, do not register any listeners
if (options.parentDb) return;
if (this.s.noListener) return;

// Add listeners
topology.on('error', createListener(this, 'error', this));
topology.on('timeout', createListener(this, 'timeout', this));
topology.on('close', createListener(this, 'close', this));
topology.on('parseError', createListener(this, 'parseError', this));
topology.once('open', createListener(this, 'open', this));
topology.once('fullsetup', createListener(this, 'fullsetup', this));
topology.once('all', createListener(this, 'all', this));
topology.on('reconnect', createListener(this, 'reconnect', this));
}

inherits(Db, EventEmitter);

// Topology
Object.defineProperty(Db.prototype, 'topology', {
enumerable: true,
Expand Down Expand Up @@ -789,11 +761,6 @@ Db.prototype.ensureIndex = deprecate(function(name, fieldOrSpec, options, callba
]);
}, 'Db.ensureIndex is deprecated as of MongoDB version 3.0 / driver version 2.0');

Db.prototype.addChild = function(db) {
if (this.s.parentDb) return this.s.parentDb.addChild(db);
this.s.children.push(db);
};

/**
* Add a user to the database.
* @method
Expand Down Expand Up @@ -963,64 +930,6 @@ Db.prototype.getLogger = function() {
return this.s.logger;
};

/**
* Db close event
*
* Emitted after a socket closed against a single server or mongos proxy.
*
* @event Db#close
* @type {MongoError}
*/

/**
* Db reconnect event
*
* * Server: Emitted when the driver has reconnected and re-authenticated.
* * ReplicaSet: N/A
* * Mongos: Emitted when the driver reconnects and re-authenticates successfully against a Mongos.
*
* @event Db#reconnect
* @type {object}
*/

/**
* Db error event
*
* Emitted after an error occurred against a single server or mongos proxy.
*
* @event Db#error
* @type {MongoError}
*/

/**
* Db timeout event
*
* Emitted after a socket timeout occurred against a single server or mongos proxy.
*
* @event Db#timeout
* @type {MongoError}
*/

/**
* Db parseError event
*
* The parseError event is emitted if the driver detects illegal or corrupt BSON being received from the server.
*
* @event Db#parseError
* @type {MongoError}
*/

/**
* Db fullsetup event, emitted when all servers in the topology have been connected to at start up time.
*
* * Server: Emitted when the driver has connected to the single server and has authenticated.
* * ReplSet: Emitted after the driver has attempted to connect to all replicaset members.
* * Mongos: Emitted after the driver has attempted to connect to all mongos proxies.
*
* @event Db#fullsetup
* @type {Db}
*/

// Constants
Db.SYSTEM_NAMESPACE_COLLECTION = CONSTANTS.SYSTEM_NAMESPACE_COLLECTION;
Db.SYSTEM_INDEX_COLLECTION = CONSTANTS.SYSTEM_INDEX_COLLECTION;
Expand Down
25 changes: 5 additions & 20 deletions lib/mongo_client.js
Expand Up @@ -6,7 +6,6 @@ const ChangeStream = require('./change_stream');
const ReadPreference = require('./read_preference');
const { MongoError } = require('./error');
const WriteConcern = require('./write_concern');
const NativeTopology = require('./topologies/native_topology');
const { maybePromise, MongoDBNamespace } = require('./utils');
const { inherits, deprecate } = require('util');
const { connect, validOptions } = require('./operations/connect');
Expand Down Expand Up @@ -241,40 +240,26 @@ MongoClient.prototype.close = function(force, callback) {

const client = this;
return maybePromise(callback, cb => {
const completeClose = err => {
client.emit('close', client);

if (!(client.topology instanceof NativeTopology)) {
for (const item of client.s.dbCache) {
item[1].emit('close', client);
}
}

client.removeAllListeners('close');
cb(err);
};

if (client.topology == null) {
completeClose();
cb();
return;
}

client.topology.close(force, err => {
const autoEncrypter = client.topology.s.options.autoEncrypter;
if (!autoEncrypter) {
completeClose(err);
cb(err);
return;
}

autoEncrypter.teardown(force, err2 => completeClose(err || err2));
autoEncrypter.teardown(force, err2 => cb(err || err2));
});
});
};

/**
* Create a new Db instance sharing the current socket connections. Be aware that the new db instances are
* related in a parent-child relationship to the original instance so that events are correctly emitted on child
* db instances. Child db instances are cached so performing db('db1') twice will return the same instance.
* Create a new Db instance sharing the current socket connections.
* Db instances are cached so performing db('db1') twice will return the same instance.
* You can control these behaviors with the options noListener and returnNonCachedInstance.
*
* @method
Expand Down
1 change: 0 additions & 1 deletion lib/operations/command.js
Expand Up @@ -28,7 +28,6 @@ const debugFields = [
'retryMiliSeconds',
'readPreference',
'pkFactory',
'parentDb',
'promiseLibrary',
'noListener'
];
Expand Down
6 changes: 0 additions & 6 deletions lib/operations/db_ops.js
Expand Up @@ -48,7 +48,6 @@ const debugFields = [
'retryMiliSeconds',
'readPreference',
'pkFactory',
'parentDb',
'promiseLibrary',
'noListener'
];
Expand Down Expand Up @@ -236,11 +235,6 @@ function createListener(db, e, object) {
function listener(err) {
if (object.listeners(e).length > 0) {
object.emit(e, err, db);

// Emit on all associated db's if available
for (let i = 0; i < db.s.children.length; i++) {
db.s.children[i].emit(e, err, db.s.children[i]);
}
}
}
return listener;
Expand Down
60 changes: 0 additions & 60 deletions test/functional/multiple_db.test.js
Expand Up @@ -7,66 +7,6 @@ describe('Multiple Databases', function() {
return setupDatabase(this.configuration);
});

/**
* @ignore
*/
it('shouldCorrectlyEmitErrorOnAllDbsOnPoolClose', {
// Add a tag that our runner can trigger on
// in this case we are setting that node needs to be higher than 0.10.X to run
metadata: { requires: { topology: 'single' } },

// The actual test we wish to run
test: function(done) {
if (process.platform !== 'linux') {
var configuration = this.configuration;
var client = configuration.newClient({ w: 1 }, { poolSize: 1 });

// All inserted docs
var numberOfCloses = 0;

// Start server
client.on('close', function(err) {
test.ok(err !== null);
numberOfCloses = numberOfCloses + 1;
});

client.connect(function(err, client) {
var db = client.db(configuration.db);

db.createCollection('shouldCorrectlyErrorOnAllDbs', function(err, collection) {
test.equal(null, err);

collection.insert({ a: 1 }, { w: 1 }, function(err) {
test.equal(null, err);
// Open a second db
var db2 = client.db('tests_2');
// Add a close handler
db2.on('close', function(err) {
test.ok(err !== null);
numberOfCloses = numberOfCloses + 1;
test.equal(2, numberOfCloses);
});

// Open a second db
var db3 = client.db('tests_3');
// Add a close handler
db3.on('close', function(err) {
test.ok(err !== null);
numberOfCloses = numberOfCloses + 1;
test.equal(3, numberOfCloses);
done();
});

client.close();
});
});
});
} else {
done();
}
}
});

/**
* Test the auto connect functionality of the db
*
Expand Down
11 changes: 5 additions & 6 deletions test/functional/operation_example.test.js
Expand Up @@ -3615,6 +3615,10 @@ describe('Operation Examples', function() {
test: function(done) {
var configuration = this.configuration;
var client = configuration.newClient(configuration.writeConcernMax(), { poolSize: 1 });
// NODE-2484: investigate double close event in Unified Topology environment
// client.on('close', function() {
// done();
// });
client.connect(function(err, client) {
// LINE var MongoClient = require('mongodb').MongoClient,
// LINE test = require('assert');
Expand All @@ -3626,14 +3630,9 @@ describe('Operation Examples', function() {
// REMOVE-LINE done();
// REMOVE-LINE var db = client.db(configuration.db);
// BEGIN
var db = client.db(configuration.db);
test.equal(null, err);

db.on('close', function() {
done();
});

client.close();
client.close(done);
});
// END
}
Expand Down

0 comments on commit eed1131

Please sign in to comment.