My node js code usually runs in less than 0.5seconds locally but when I deploy on firebase function it sometimes take up to 3 seconds to 5 seconds to return the response I want. is there a way to fix this perfomance issue? the problem is I do all the computation in a single request function because I need to parse text from that request and use it in my code but I couldn't figure out any other way to fix it. any suggestions would be appreciated and thanks in advance
exports.Response = functions.https.onRequest(async (req, res) => {
const original = req.query.text;
var returned = original.split(',');
var startLat= returned[0];
var startLong = returned[1];
var endLat = returned[2];
var endLong = returned[3];
var maxDistance = returned[4];
var output = binding.Main(startLat, startLong, endLat, endLong, Number(maxDistance));
var Response = output.split(' ');
var Array = [];
for(i = 0; i<Response.length ; i++)
{
Array.push(Response[i]);
}
var data = {};
data.table = [];
var obj =
{
Start: Array[0]
}
data.table.push(obj);
for (i=1; i < Array.length-1 ;i+=7)
{
var obj =
{
transportType: Array[i],
Price: Array[i+1],
Type: Array[i+2],
startLatitude: Array[i+3],
startLongitude: Array[i+4],
endLatitude: Array[i+5],
endLongitude: Array[i+6]
}
data.table.push(obj);
}
var obj = {
TotalPrice: Array[Array.length-1]
}
data.table.push(obj);
res.status(200).json({
data
})
});
I know code is unprofessional but am still new to node js and addons so I tried my best to get the required output. any suggestions/notes would be taken and appreciated. Also if any further code/explanation is required please let me know.
Helping Renaud Tarnec's reply to be posted as an answer:
The delay you encounter after deploying your Cloud function is most probably not caused by your code but by the cold start ("Functions are stateless, and the execution environment is often initialized from scratch, which is called a cold start"). See more details and possible improvement tips at: https://cloud.google.com/functions/docs/bestpractices/tips, https://youtube.com/watch?v=v3eG9xpzNXM, https://youtube.com/watch?v=IOXrwFqR6kY, https://medium.com/#duhroach/improving-cloud-function-cold-start-time-2eb6f5700f6
Related
can you help me with getting data out of an influx DB instance inside a nodeJS application?
I have tried https://github.com/node-influx/node-influx and https://github.com/vicanso/influxdb-nodejs with only little success.
const Influx = require('influxdb-nodejs');
//Database connection Influx
const client = new Influx('http://redacted/db');
exports.connectInflux = function () {
var date = new Date();
var timeTo = date.toISOString()
date.setDate(date.getDate() - 4)
var timeFrom = date.toISOString()
var reader = client.query('impulse')
.where('location', 'SA08')
.where('time', timeFrom, '>')
.where('time', timeTo, '<')
.then(function (data) {
console.info(data.results[0].series[0].values)
return data.results[0].series[0].values
})
.catch(console.error);
// I get the measurements
client.showMeasurements()
.then(console.info)
.catch(console.error)
}
With this code snippet, at least I can get the data in the console. But when trying to work with it, I only get an empty array. Can you spot any mistake here?
I am thankful for every hint!
Thanks!
Remember that by default, time must be in nanoseconds. You are using milliseconds.
I'm trying to delete all nodes with a date greater than '2017-04-05' with a bulk operation with a firebase function. Can you spot what I'm doing wrong here?
The 2 nodes that should get deleted are the ones in red:
Here's the code that is failing - can you see what's wrong? Also, I'm concerned about the performance of this (I'll only run it once in a while though). If there are millions of games in the list, should that concern me if I only run this once a day?
exports.remove = functions.https.onRequest((req, res) => {
const deleteBeforeDate = req.query.deleteBeforeDate;
var ref = admin.database().ref('games');
var keysToDelete = {};
for (var game in this.games) {
var date = items[i]['.date'];
if(date.value > '2017-04-05'){
keysToDelete[game.key] = null;
}
}
this.ref.update(keysToDelete);
});
Thank you very much,
Mike
To determine the keys to delete, you'll need to attach a listener. Since that is needed, you might as well create a query that selects the correct children and deletes only those:
var ref = admin.database().ref('games');
var deleteAfterDate = ref.orderByChild('date').startAt('2017-04-05');
deleteAfterDate.once('value').then(function(snapshot) {
var updates = {};
snapshot.forEach(function(child) {
updates[child.key] = null;
});
ref.update(updates);
});
I have a list of 125,000 + Id numbers.
I am making a request to an api to get more information for each one.
But my problem is that the api will stop giving me a response if I request more then 6 per second.
I need a way to control the speed of the requests.
Just use a function called by setInterval to do the actual API querying ?
Simple example:
var ids = [ /* big array here */ ];
function queryAllIds(ids, callback) {
var processedIds = [];
var lastProcessedId = 0;
var processedIdCount = 0;
var intervalId;
function queryApi() {
var idToProcess = lastProcessedId++;
doActualQuery(ids[idToProcess], function(result) {
processedIds[idToProcess] = result;
processedIdCount++;
if (processedIdCount === ids.length) {
nextTick(callback, processedIds);
}
});
}
if (intervalId && lastProcessedId === ids.length)
clearInterval(intervalId);
}
intervalId = setInterval(queryApi, 1000/6);
}
queryAllIds(ids, function (processedIds) {
// Do stuff here
});
We ended up using rate limiter which provided the rate limiting we needed right out of the box. https://www.npmjs.com/package/limiter
I have node js files restservice.js and mysql.js
In mysql.js i have two functions as elementlevelpricing and pricingdetail
In restservice.js i have api which has the code as :
var workload = req.body;
var workloadinfo = {
workloadId: workload.workloadId,
ownerId: workload.ownerId,
uniqueName: workload.uniqueName,
name: workload.name
}
if(workload.elements && workload.elements.length > 0)
{
var elementlevelpricingSummary = {};
var elementArray = [];
var elementinfo = {};
var metadataModified = {};
var pricingDetail = {};
async.forEachSeries(workload.elements, createResponse, function (err) {
res.send(workloadinfo);
});
function createResponse(elements,callback) {
var resourceIdentifierArray = [];
elementinfo = elements;
resourceIdentifierArray.push(elements.uri);
var resourceIdentifiers = resourceIdentifierArray.join(',');
// Get element level pricing summary
mysql.elementlevelpricing(resourceIdentifiers, function(result){
// do some stuff here
return callback();
});
};
};
I need to call the function pricingdetail in mysql.js and append the result to global variable workloadinfo (which already should have result set of elementlevelpricing and Can thats what is sent within foreachSeries ). Can anyone suggest me the profession way to accomplish this?
Use asynchronous functions. The whole point of Node.js is to avoid blocking. Blocking in Node.js is worse than blocking in threaded environments, because there aren't any other threads (though there may be other clustered processes). You're blocking the only event loop available. That means that your whole server has to wait, doing absolutely no work until your I/O is done.
I'm having some issues using Node.js as a http client against an existing long polling server. I'm using 'http' and 'events' as requires.
I've created a wrapper object that contains the logic for handling the http.clientrequest. Here's a simplified version of the code. It works exactly as expected. When I call EndMe it aborts the request as anticipated.
var http = require('http');
var events = require('events');
function lpTest(urlHost,urlPath){
this.options = {
host: urlHost,
port: 80,
path: urlPath,
method: 'GET'
};
var req = {};
events.EventEmitter.call(this);
}
lpTest.super_ = events.EventEmitter;
lpTest.prototype = Object.create(events.EventEmitter.prototype, {
constructor: {
value: lpTest,
enumerable: false
}
});
lpTest.prototype.getData = function getData(){
this.req = http.request(this.options, function(res){
var httpData = "";
res.on('data', function(chunk){
httpData += chunk;
});
res.on('end', function(){
this.emit('res_complete', httpData);
}
};
}
lpTest.prototype.EndMe = function EndMe(){
this.req.abort();
}
module.exports = lpTest;
Now I want to create a bunch of these objects and use them to long poll a bunch of URL's. So I create an object to contain them all, generate each object individually, initiate it, then store it in my containing object. This works a treat, all of the stored long-polling objects fire events and return the data as expected.
var lpObject = require('./lpTest.js');
var objWatchers = {};
function DoSomething(hostURL, hostPath){
var tempLP = new lpObject(hostURL,hostPath);
tempLP.on('res_complete', function(httpData){
console.log(httpData);
this.getData();
});
objWatchers[hosturl + hostPath] = tempLP;
}
DoSomething('firsturl.com','firstpath');
DoSomething('secondurl.com','secondpath);
objWatchers['firsturl.com' + 'firstpath'].getData();
objWatchers['secondurl.com' + 'secondpath'].getData();
Now here's where it fails... I want to be able to stop a long-polling object while leaving the rest going. So naturally I try adding:
objWatchers['firsturl.com' + 'firstpath'].EndMe();
But this causes the entire node execution to cease and return me to the command line. All of the remaining long-polling objects, that are happily doing what they're supposed to do, suddenly stop.
Any ideas?
Could it have something to do with the fact that you are only calling getData() when the data is being returned?
Fixed code:
function DoSomething(hostURL, hostPath){
var tempLP = new lpObject(hostURL,hostPath);
tempLP.on('res_complete', function(httpData){
console.log(httpData);
});
tempLP.getData();
objWatchers[hosturl + hostPath] = tempLP;
}
I have seemingly solved this, although I'm note entirely happy with how it works:
var timeout = setTimeout(function(){
objWatchers['firsturl.com' + 'firstpath'].EndMe();
}, 100);
By calling the closing function on the object after a delay I seem to be able to preserve the program execution. Not exactly ideal, but I'll take it! If anyone can offer a better method please feel free to let me know :)