5

nodejs mongodb driver drops connection when idle and does not reconnect.

Background

The script below connects to mongodb and stores a reference to the database in a global variable "db"

config = require("./config.js");
express = require("express");
mongodb = require("mongodb"); 

db = null;

options = {
  auto_reconnect: true,
  db: {
    w: 1
  }
};

mongodb.MongoClient.connect(config.mongo, options, function(err, database) {

  if (err !== null)
    return console.log(err);

  db = database;
  console.log("successfully connected to mongodb");

  db.on("close", (function() {
    return console.log("Connection to database closed automagically " + arguments);
  }));

  db.on("error", function(err) {
    return console.log("Db error " + err);
  });

  app.listen(port);

  return console.log("listening for connections on " + port);

});

Whenever i receive an insert request from client the following function is invoked:

insert = function(collectionName, object) {
  return db.collection(collectionName).insert(object, {w: 1}, (function(err) {
    return console.log("insert complete with err = " + err);
  }));
};

Issue

When the server receives an insert request after a long time it fails silently or sometimes throws an error stating unable to insert object (Error: failed to connect to [host:port])

Question

Is there a way to prevent this behaviour? I have tried to use auto_reconnect option and write concern of 1 but none of these have helped.

Thanks!

Furqan Zafar
  • 1,471
  • 1
  • 13
  • 17
  • 1
    [Connection pools](http://stackoverflow.com/questions/10656574/how-to-manage-mongodb-connections-in-a-nodejs-webapp/14464750#14464750) might help you maintain redundancy, at least, if you expect some connections to fail. Then, periodically checking the pool with meaningless "pings", you can confirm that the connections are dropping and make a few new ones then and there. I'm not sure if they would all drop at about the same time, or in some staggered way, but it might be worth a shot. – TheEnvironmentalist Jul 22 '14 at 07:29

1 Answers1

4

Solved!

  1. Set server.socketoptions.keepAlive to 1. Simply update the options object like so:

    options = {
      auto_reconnect: true,
      db: {
        w: 1
      },
      server: {
        socketOptions: {
          keepAlive: 1
        }
      }
    };
    
  2. Ping the database at regular intervals. Here's a code snippet that does exactly that:

    printEventCount = function() {
      db.collection("IOSEvents").count(function(err, numberOfEvents) {
        console.log(new Date() + ": error = " + err + ", number of events = " + numberOfEvents);
        ping();
      });
    };
    
    ping = function() {
      if (config.pingPeriod === 0)
        return;    
      setTimeout(printEventCount, config.pingPeriod);
    };
    
Community
  • 1
  • 1
Furqan Zafar
  • 1,471
  • 1
  • 13
  • 17
  • As of driver 2.1, you don't need to set auto_reconnect: true explicitly. http://mongodb.github.io/node-mongodb-native/2.1/api/Server.html – Sercan Ozdemir May 05 '16 at 11:04
  • 2
    socketOptions.keepAlive is a number (ms), not a boolean. Setting it to 1 probably isn't a good idea. mongolabs suggests a 30 second (30000) setting: https://gist.github.com/mongolab-org/9959376 – Allan Nienhuis Jul 21 '16 at 18:23