6

I am connecting a nodejs app to my mongodb database using the following:

const url = 'mongodb://localhost:27017/?replicaSet=rs'
let client = new MongoClient(url, { 
  useNewUrlParser: true,
  connectTimeoutMS: 60000,    
  socketTimeoutMS: 60000, 
 })
try {
  let dbclient = await client.connect()
  console.log(dbclient)
  const db = dbclient.db('test')
  const collection = db.collection('accounts')
  const changeStream = collection.watch(pipeline)
  changeStream.on("change", function(change) {
    console.log('changed', change)
  })
} catch (err) {
  console.log('mongo err:', err)
}

This works perfectly, however it regularly loses connection after a few minutes with the error:

Uncaught MongoNetworkError: connection 6 to localhost:27017 timed out

According to the documentation it should automatically reconnect up to 30 tries upon error, however it does not appear to make any further attempts to reconnect.

I will also need to run some additional logic on reconnect to properly handle local state.

How can I catch and handle these errors?

Edit: While I'm still not getting other events, I am getting 'reconnect' events after the errors occur. So it seems I can at least react to the errors, but still not actually catch them.

3 Answers3

4

Just add to the connection keepAlive: true, or specific time keepAlive: 300000

See the example here:https://ide.c9.io/ibrahimth/mongo

const MongoClient = require('mongodb').MongoClient;
const assert = require('assert');

// Connection URL
const url = 'mongodb://localhost:27017/?replicaSet=rs'
// Database Name
const dbName = 'test';

// create a client, passing in additional options
const client = new MongoClient(url, {
   keepAlive: true,
  connectTimeoutMS: 60000,    
  socketTimeoutMS: 60000, 
});

// Use connect method to connect to the server
client.connect(function(err) {
  assert.equal(null, err);
  console.log("Connected correctly to server");
const db = client.db(dbName);
createCollated(db, function() {
    client.close();
  });


});


function createCollated(db, callback) {
  db.createCollection('acount',
    {
      'collation' :
        { 'acountnam': 'firstacount' }
    },

    function(err, results) {
      console.log("Collection created.");
      callback();
    }
  );
};

For more information: http://mongodb.github.io/node-mongodb-native/3.0/tutorials/collations/

I_Al-thamary
  • 3,385
  • 2
  • 24
  • 37
  • Actually finally ran into the issue again today, using this fix. Interestingly the error I received now is slightly different, with the error wrapped in an object (keys: name, message, stack) than just a plain message. Still not finding a way to catch it, though. –  Feb 05 '19 at 22:45
  • @Thebluefish try to do this `socketTimeoutMS: 3000000,` `connectionTimeoutMS: 3000000,` `keepAlive:3000000` – I_Al-thamary Feb 06 '19 at 03:43
  • I don't think increasing the existing timeout is going to help me handle these errors as they come up. They may cause them to happen less often, but I need to actually *properly* handle them when they happen. –  Feb 06 '19 at 08:28
  • @Thebluefish I found this it may help:https://stackoverflow.com/questions/18688282/handling-timeouts-with-node-js-and-mongodb – I_Al-thamary Feb 06 '19 at 12:26
  • I've tried listening to 'close' and 'error' events on just about everything I can think of related to the connection, however none of them seem to ever get hit. –  Feb 07 '19 at 23:35
  • @Thebluefish try to remove `useNewUrlParser: true,` and put `socketTimeoutMS: 3000000, connectionTimeoutMS: 3000000, keepAlive:3000000` – I_Al-thamary Feb 08 '19 at 04:16
  • I'm very confused how collations will help me handle this error that's appearing. The example code still produces the occasional error upon testing. –  Feb 09 '19 at 00:43
  • @Thebluefish It works fine but I noticed your comment and I look for an answer and I found that the problem may appear in specific mongo version see this:https://github.com/Automattic/mongoose/issues/4789. So, try to downgrade your version or upgrade it. – I_Al-thamary Feb 14 '19 at 17:06
0

Try this

var MongoClient = require('mongodb').MongoClient;
 var mongo = {};
 mongo.init = function() {
 MongoClient.connect('mongodb://localhost:27017/db',function(err, db) {
    if (err) {
      console.log('Err',err);
    } else {
      mongo.DB = db;
    }
    db.on('reconnect', function() {
      mongo.DB = db;
    });
  }
}
Vignesh
  • 1,140
  • 1
  • 9
  • 17
  • Handling the `reconnect` event doesn't help handling the error itself. Also, I am unsure how to properly handle the change stream in this case. When the `reconnect` event fires and no error occurs, the change stream still receives events. However when the event fires after an error, it does not. I am not finding a good way to distinguish between the two when handling the `reconnect` event. Ideally, I wish to handle the actual error itself. –  Feb 09 '19 at 00:41
0

I will suggest you add reconnectTries which acts as Server attempt to reconnect #times, and add other options which should stabilize your connection, then you modify your codes back to:

const url = 'mongodb://localhost:27017/?replicaSet=rs'
let client = new MongoClient(url, { 
  useNewUrlParser: true,
  connectTimeoutMS: 30000,    
  socketTimeoutMS:  360000, 
  useMongoClient: true,
  keepAlive: true,
  reconnectTries: 30
 })
try {
  let dbclient = await client.connect()
  console.log(dbclient)
  const db = dbclient.db('test')
  const collection = db.collection('accounts')
  const changeStream = collection.watch(pipeline)
  changeStream.on("change", function(change) {
    console.log('changed', change)
  })
} catch (err) {
  console.log('mongo err:', err)
}
antzshrek
  • 9,276
  • 5
  • 26
  • 43