Tatu Bogdan Tatu Bogdan - 3 years ago 163
Node.js Question

Firebase database querying taking to much time in Cloud Function

I use nodejs as a backend hosted on the firebase functions to query my firebase database, I have this code:

const functions = require('firebase-functions');
const admin = require('firebase-admin');
const cors = require('cors')({origin: true});
admin.initializeApp(functions.config().firebase);
const express = require('express')


exports.getAjax = functions.https.onRequest((request, response) => {
cors(request, response, () => {
console.log("request.body :", JSON.stringify(request.body));
console.log("request.query :", JSON.stringify(request.query));


var date = {
startDate: request.body.startDate,
endDate: request.body.endDate
}
var db = admin.database();
var logsDbPath = 'logs';
var usersDbPath = 'users';
var ref = db.ref(logsDbPath);
var tags;
db.ref(usersDbPath).once('value').then(function(tagsSnapshot) {
tagsSnapshot.forEach(function(tagSnapshot) {
var tagId = tagSnapshot.key;
tagSnapshot.forEach(function(sessSnapshot) {
var userSessId = sessSnapshot.key;
var userInfo = sessSnapshot.val();
});
});

tags = JSON.parse(JSON.stringify(tagsSnapshot.val()));
console.log(tags);
});
});
});


My main problem is that
console.log(tags);
and actually finishing the query and get the value for tags took ~38 sec in this case (sometimes takes ~ 1 min), I will put picture bellow:

execution time

And that object it's not that big at all, like 100 rows with 4 properties each, I don't think it should take that much, probably I did something wrong, but where?, I also have to write a promise or a callback in order to send that tags var response on the front end, cause the function finish before I get any value on tags(see picture), I come from a PHP background and this asynchronous javascript concept it's quite new for me.

Answer Source

You're not sending any response back to the client, which means that the function will keep running until it times out.

To make sure the function runs only for as long as needed, send a response to the client when you've loaded the data:

exports.getAjax = functions.https.onRequest((request, response) => {
  cors(request, response, () => {
    console.log("request.body :", JSON.stringify(request.body)); 
    console.log("request.query :", JSON.stringify(request.query));


    var date = {
      startDate: request.body.startDate,
      endDate: request.body.endDate
    }
    var db = admin.database();
    var logsDbPath = 'logs';
    var usersDbPath = 'users';
    var ref = db.ref(logsDbPath);
    var tags;
    db.ref(usersDbPath).once('value').then(function(tagsSnapshot) {
      tagsSnapshot.forEach(function(tagSnapshot) {
        var tagId = tagSnapshot.key;
        tagSnapshot.forEach(function(sessSnapshot) {
          var userSessId = sessSnapshot.key;
          var userInfo = sessSnapshot.val();
        });
      });

      tags = JSON.parse(JSON.stringify(tagsSnapshot.val()));
      console.log(tags);

      // Send the response to the client, which also ends the function
      response.status(200).send(tags);
    });
  });
});   

Aside from that it's hard to say much. Keep in mind that Cloud Functions is in beta and is constantly changing, we have no way of knowing whether this is a cold start or warm start, and we can't see your project to inspect what's going on.

If you'd like to have more help here, I recommend that you try to reproduce the problem in a more troubleshoot-friendly environment. For example, can you reproduce the perfor,ance problem with a local node.js process?

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download