Skip to content

Commit 0211c59

Browse files
committed
NODE-507 Repeatedly Switching DBs on a single connection increases memory usage
1 parent 7d250d1 commit 0211c59

File tree

3 files changed

+41
-23
lines changed

3 files changed

+41
-23
lines changed

lib/db.js

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ var Db = function(databaseName, topology, options) {
9999
this.s = {
100100
// Database name
101101
databaseName: databaseName
102+
// DbCache
103+
, dbCache: {}
102104
// Children db's
103105
, children: []
104106
// Topology
@@ -123,6 +125,8 @@ var Db = function(databaseName, topology, options) {
123125
, nativeParser: options.nativeParser || options.native_parser
124126
// Promise library
125127
, promiseLibrary: promiseLibrary
128+
// No listener
129+
, noListener: typeof options.noListener == 'boolean' ? options.noListener : false
126130
}
127131

128132
// Ensure we have a valid db name
@@ -180,6 +184,7 @@ var Db = function(databaseName, topology, options) {
180184

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

184189
// Add listeners
185190
topology.once('error', createListener(self, 'error', self));
@@ -968,24 +973,40 @@ Db.prototype.addChild = function(db) {
968973
* Create a new Db instance sharing the current socket connections.
969974
* @method
970975
* @param {string} name The name of the database we want to use.
976+
* @param {object} [options=null] Optional settings.
977+
* @param {boolean} [options.noListener=false] Do not make the db an event listener to the original connection.
971978
* @return {Db}
972979
*/
973-
Db.prototype.db = function(dbName) {
980+
Db.prototype.db = function(dbName, options) {
981+
options = options || {};
974982
// Copy the options and add out internal override of the not shared flag
975-
var options = {};
976983
for(var key in this.options) {
977984
options[key] = this.options[key];
978985
}
979986

987+
// Do we have the db in the cache already
988+
if(this.s.dbCache[dbName]) {
989+
return this.s.dbCache[dbName];
990+
}
991+
980992
// Add current db as parentDb
981-
options.parentDb = this;
993+
if(options.noListener == null || options.noListener == false) {
994+
options.parentDb = this;
995+
}
996+
982997
// Add promiseLibrary
983998
options.promiseLibrary = this.s.promiseLibrary;
984999

9851000
// Return the db object
9861001
var db = new Db(dbName, this.s.topology, options)
1002+
9871003
// Add as child
988-
this.addChild(db);
1004+
if(options.noListener == null || options.noListener == false) {
1005+
this.addChild(db);
1006+
}
1007+
1008+
// Add the db to the cache
1009+
this.s.dbCache[dbName] = db;
9891010
// Return the database
9901011
return db;
9911012
};

test/functional/insert_tests.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -572,9 +572,6 @@ exports.shouldThrowErrorIfSerializingFunctionUnOrdered = {
572572
collection.insert({i:1, z:func }, {w:1, serializeFunctions:true, ordered:false}, function(err, result) {
573573
test.equal(null, err);
574574

575-
console.log("--------------------------------- 0")
576-
console.dir(result)
577-
578575
collection.findOne({_id:result.ops[0]._id}, function(err, object) {
579576
console.dir(object)
580577
test.equal(func.toString(), object.z.code);

test/functional/multiple_db_tests.js

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ exports.shouldCorrectlyEmitErrorOnAllDbsOnPoolClose = {
77
// Add a tag that our runner can trigger on
88
// in this case we are setting that node needs to be higher than 0.10.X to run
99
metadata: { requires: {topology: 'single'} },
10-
10+
1111
// The actual test we wish to run
1212
test: function(configuration, test) {
1313
if(process.platform !== 'linux') {
@@ -22,7 +22,7 @@ exports.shouldCorrectlyEmitErrorOnAllDbsOnPoolClose = {
2222
db.on("close", function(err) {
2323
numberOfCloses = numberOfCloses + 1;
2424
})
25-
25+
2626
db.open(function(err, db) {
2727
db.createCollection('shouldCorrectlyErrorOnAllDbs', function(err, collection) {
2828
test.equal(null, err);
@@ -49,7 +49,7 @@ exports.shouldCorrectlyEmitErrorOnAllDbsOnPoolClose = {
4949
db.close();
5050
});
5151
});
52-
});
52+
});
5353
} else {
5454
test.done();
5555
}
@@ -58,12 +58,12 @@ exports.shouldCorrectlyEmitErrorOnAllDbsOnPoolClose = {
5858

5959
/**
6060
* Test the auto connect functionality of the db
61-
*
61+
*
6262
* @ignore
6363
*/
6464
exports.shouldCorrectlyUseSameConnectionsForTwoDifferentDbs = {
6565
metadata: { requires: { topology: ['single', 'replicaset', 'sharded', 'ssl', 'heap', 'wiredtiger'] } },
66-
66+
6767
// The actual test we wish to run
6868
test: function(configuration, test) {
6969
var client = configuration.newDbInstance({w:1}, {poolSize:1});
@@ -77,7 +77,7 @@ exports.shouldCorrectlyUseSameConnectionsForTwoDifferentDbs = {
7777
var secondDb = client.db(configuration.db_name + "_2");
7878
secondDb.createCollection('shouldCorrectlyUseSameConnectionsForTwoDifferentDbs', function(err, collection) {
7979
// Insert a dummy document
80-
collection.insert({a:20}, {safe: true}, function(err, r) {
80+
collection.insert({a:20}, {safe: true}, function(err, r) {
8181
test.equal(null, err);
8282

8383
// Query it
@@ -87,21 +87,21 @@ exports.shouldCorrectlyUseSameConnectionsForTwoDifferentDbs = {
8787
// Use the other db
8888
client.createCollection('shouldCorrectlyUseSameConnectionsForTwoDifferentDbs', function(err, collection) {
8989
// Insert a dummy document
90-
collection.insert({b:20}, {safe: true}, function(err, r) {
91-
test.equal(null, err);
90+
collection.insert({b:20}, {safe: true}, function(err, r) {
91+
test.equal(null, err);
9292

9393
// Query it
9494
collection.findOne({}, function(err, item) {
9595
test.equal(20, item.b);
9696

9797
test.equal(null, err);
9898
client.close();
99-
second_test_database.close();
100-
test.done();
101-
});
99+
second_test_database.close();
100+
test.done();
101+
});
102102
});
103103
});
104-
});
104+
});
105105
});
106106
});
107107
});
@@ -114,7 +114,7 @@ exports.shouldCorrectlyUseSameConnectionsForTwoDifferentDbs = {
114114
*/
115115
exports.shouldCorrectlyHandleMultipleDbsFindAndModifies = {
116116
metadata: { requires: { topology: ['single', 'replicaset', 'sharded', 'ssl', 'heap', 'wiredtiger'] } },
117-
117+
118118
// The actual test we wish to run
119119
test: function(configuration, test) {
120120
var db = configuration.newDbInstance({w:1}, {poolSize:1});
@@ -138,10 +138,10 @@ exports.shouldCorrectlyHandleMultipleDbsFindAndModifies = {
138138
*/
139139
exports['should not leak listeners'] = {
140140
metadata: { requires: { topology: ['single', 'replicaset', 'sharded', 'ssl', 'heap', 'wiredtiger'] } },
141-
141+
142142
// The actual test we wish to run
143143
test: function(configuration, test) {
144-
var MongoClient = configuration.require.MongoClient;
144+
var MongoClient = configuration.require.MongoClient;
145145
MongoClient.connect(configuration.url(), function(err, db) {
146146
for (var i = 0; i < 100; i++) {
147147
db.db("test");
@@ -151,4 +151,4 @@ exports['should not leak listeners'] = {
151151
test.done();
152152
});
153153
}
154-
}
154+
}

0 commit comments

Comments
 (0)