Wednesday, 24 May 2017

MongoDB, Node.JS - "Error: EMFILE: too many open files"

Versions MongoDB: 3.4.3 Express: 4.1.4 Node: 7.8.0

Background: working on a project that utilizes a Node.JS+Express server that accesses a MongoDB server (on the same box) to both update and read. The updates are coming from a group of Raspberry Pi’s posting certain environment details (3 Pi’s posting at a rate of 1 per 5 seconds); the reads are coming from a variety of sources. In my current setup, I am getting the error noted in the title: “Error: EMFILE: too many open files” due to too many open connection to the MongoDB server. The ‘ulimit’ for open files is set at 1024 and, as you would expect at the post rate per Pi with 3 Pi’s, it takes about 20 minutes to generate enough connections to produce the error with no reads. Many recommendations to “solve” this issue is to increase the open file limit, but, if the Express server is to run indefinitely, it will just push back the amount of time until the error occurs instead of actually fixing the issue.

Declared outside query functions:

mongo = require('mongodb').MongoClient;

Update Function:

function update(input){
  var pairlist = [];
  var rpiMac = "";
  for(var line in input){
    if(line === "rpiMac")
      rpiMac = input[line];
    else
      pairlist.push(input[line]);
  }

  var d = new Date();
  var current_time = Math.round(d.getTime() / 1000);

  var MONGO_DB = process.env.MONGO_DB;

  var MongoConnect = mongo.connect(MONGO_DB, function(err, db) {
    if(err)
      return {code:500,msg:"Can't connect to MongoDB."};

    var table = db.collection('proximity_details');

    for(var i = 0; i < pairlist.length; i++){
      var cond = {rpiMac:rpiMac, clientMac:pairlist[i][0]};
      var set = {rpiMac:rpiMac,clientMac:pairlist[i][0],rssi:parseFloat(pairlist[i][1]),seenEpoch:current_time};
      var optns = {upsert:true};

      if(['C8:C0:77:D5:0C:72','C7:1F:6A:B0:E5:CC','C1:64:41:BF:40:F3','DF:BE:DA:B2:47:CB'].indexOf(pairlist[i][0]) >= 0){
        table.findOneAndUpdate(cond,set,optns);
      }
    }
    db.close();
  });

  return {code:200,msg:"DB successfully updated."};
};

/****EXPORT FUNCTION(S)****/
exports.update = update;

Read Function:

function proximity(res){
  var d = new Date();
  var currentEpoch = Math.round(d.getTime() / 1000);
  var pastFiveMin = currentEpoch - 300;

  var MONGO_DB = process.env.MONGO_DB;
  var MongoConnect = mongo.connect(MONGO_DB,function(err,db){
    var query = {seenEpoch : { $gt : pastFiveMin }};
    db.collection('proximity_details').find(query).toArray(function(err,docs){
      res.status(200);
      res.send(docs);
      //console.log(docs);
    });
    db.close();
  });
};

/****EXPORT FUNCTION(S)****/
exports.proximity = proximity;

So, my understanding is that the connection should just close at the end of the asynchronous “MongoClient.connect()” function call, but that doesn’t seem to be occurring. There is not a synchronous version of the function set to query MongoDB to then force a connection close nor is there a way I am aware of to close an asynchronous call. I believe older versions of the Node.JS driver for MongoDB allow for explicit connection closing, but have not found a workable solution thus far.

Wouldn’t be surprised if I’m overlooking something silly; JS is not my strongest language by any means. Any ideas? Thanks in advance!



via ThatDiggityDogg

No comments:

Post a Comment