Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

nodejs mongodb driver drops connection when idle

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!

like image 431
Furqan Zafar Avatar asked Oct 01 '22 06:10

Furqan Zafar


1 Answers

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);
    };
    
like image 63
Furqan Zafar Avatar answered Oct 16 '22 08:10

Furqan Zafar