Handling timeouts with Node.js and mongodb
UPD:
Based on this post, looks like they've deployed fix that will do the same as what we do here. Not sure if this is already within npm (15.10.13). https://github.com/mongodb/node-mongodb-native/issues/1092#ref-commit-2667d13
After some investigation I've managed to understand what is going on there:
Every time you call any method to deal with database (find, update, insert, etc.) it creates cursor, that has own ID and registers itself to EventEmitter of Db for being called back later. In meantime it registers itself to _notReplied object within same CallBackStore.
But once connection is closed, I couldn't locate anything that would iterate through _notReplied cursors and would trigger them with errors or any logic with timers (it still might be somewhere there). So I've managed to write small work around, that does force triggers cursors with error when DB emits close
event:
new mongodb.Db('testdb', new mongodb.Server('localhost', 27017, { }), { safe: true }).open(function (err, db) { if (!err) { db.on('close', function() { if (this._callBackStore) { for(var key in this._callBackStore._notReplied) { this._callHandler(key, null, 'Connection Closed!'); } } }); // ... } else { console.log(err) }});
I recommend using first approach instead of MongoClient. Reasons are few: for example when you close connection and then call .find
it will properly trigger error in callback, while with MongoClient it won't.
If you are using MongoClient:
MongoClient.connect('mongodb://localhost:27017/testdb', function(err, db) { if (!err) { db.on('close', function() { if (this._callBackStore) { for(var key in this._callBackStore._notReplied) { this._callHandler(key, null, 'Connection Closed!'); } } }); // ... } else { console.log(err); }});
What this will do? Once connection is closed, it will iterate through All _notReplied cursors and trigger events for them with error Connection Closed!
.
Test case:
items.find({ }).toArray(function(err, data) { if (!err) { console.log('Items found successfully'); } else { console.log(err); }});db.close();
That will force close database connection and trigger close
event that you handle earlier and will make sure that cursor will be closed.
UPD:I've added Issue on GitHub: https://github.com/mongodb/node-mongodb-native/issues/1092 we'll see what they say regarding this.
I had the same problem, and found this page from google.But your choosed answer didn't resolve the problem and it is as same as you, this._callBackStore can't use
but i tried to wrap the Mongo, and it seems work fine
var MongoClient = require('mongodb').MongoClient;var mongo = {};mongo.init = function() { MongoClient.connect('mongodb://localhost:27017/testdb', function(err, db) { if (err) { mongo.DB = ''; } else { mongo.DB = db; } db.on('close', function() { mongo.DB = ''; }); db.on('reconnect', function() { mongo.DB = db; }); }} mongo.getdb = function(callback) { if (mongo.DB) { callback(null, mongo.DB); } else { callback('can not connect to db', null); }}module.exports = mongo;
firstly start server and init() it
and then you can require it and use
mongo.getdb(function(err, db) { if (err) { console.log(err); } else { db.collection('user').find({'xxx':'xxx'}).toArray(function(err, items) { console.log(items); }); }});
After some further investigation, it seems that you can't specify "offline" timeouts such as in the scenario outlined above. The only timeout that can be specified is one which informs the server to timeout the cursor after 10 minutes of inactivity, however as in the scenario above the connection to the server is down this does not work.
For reference, I found the information here: https://github.com/mongodb/node-mongodb-native/issues/987#issuecomment-18915263 by who I believed to be one of the main contributors to the project.