Google cloud functions - setInterval function quits after 15 mins - node.js

My app uses a Firebase function that is triggered when my Firebase realtime database is modified.
The function initiates a setInterval function that is supposed to loop for an hour then terminate....HOWEVER it seems to quit after 15mins.
Im guessing this is a restriction put in place by Firebase...does anyone know how I can get around this?See code below
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
//this gets triggered when db is updated
exports.onActiveUpdate = functions.database
.ref('/pathToRealtimeDb').onUpdate(() => {
let counter = setInterval(() => {
//count down from 60 mins to zero then exit
}, 60000); //end setInterval
});

Related

Run function after 2 sec delay in nodejs

This is a simple node js hander in cloud function that is getting called . It is calling another function redisApiCacheRemove as below . I want to call this function after 2 sec of delay , can do it . Something like , wait for 2 sec and then run that function redisApiCacheRemove
exports.drm = (request, response) => {
const pubsubmessage = Buffer.from(request.body.message.data, 'base64').toString();
console.log('message received >>' + pubsubmessage);
const pubsubMessage = JSON.parse(pubsubmessage);
console.log(pubsubMessage.entity.id);
redisApiCacheRemove(pubsubMessage.entity.id, pubsubMessage.entity.event);
return response.status(200).send();
;
You just need to use setTimeout like this
const delay = 2000 // In milliseconds
setTimeout(() => {
// The code you want to execute after 2 seconds goes here
}, delay)
setTimeout also returns timeoutID that you can use to clear the timeout if you want to cancel the timeout before it happens, e.g
const delay = 2000 // In milliseconds
const timeoutID = setTimeout(() => {
// The code you want to execute after 2 seconds goes here
}, delay)
clearTimeout(timeoutID) // Will cancel the timeout above

Logging slow redis operations in NodeJS

In the Nodejs app, I am using 'ioredis' npm module to execute all redis operations. Redis is used heavily in the whole service. But I have seen for 1 of 1000 call, redis latency is increased to 400ms.
I am trying to log all redis operations exceeding a certain timestamp in the code itself. Suggest some ways to log such commands, without slowing any other operation.
Thanks.
You can try this :
var Moment = require('moment');
var start_time = Moment();
//->>> In case of Promises
redisOperation(arguments)
.then(function() {
var time_taken = Moment() - start_time;
console.log(time_taken); //However you want to log, use the logger function here
});
//->>> In case of Callback Function
redisOperation(arguments, function() {
var time_taken = Moment() - start_time;
console.log(time_taken); //However you want to log, use the logger function here
cb();
});
For time being, I wasn't able to find any inbuilt solution. But I handled this by creating a wrapper before the execution of Redis operations.
const traceTime = function (fn) {
return async function (...args) {
const startTime = Date.now();
const executionResp = await fn.apply(this, args);
const endTime = Date.now();
};
}
/* wrap the redis operations with traceTime */
set = traceTime(set); // redis set operation
get = traceTime(get); // redis get operation
/* use redis set operation, wherever you want to use,
it will log startTime and endTime and execute redis operation from there */
set(key, value, (err, response) => {
// err and response handler
});

Telegram Bot (Telegraf) stuck in infinite loop

My function named status sending information about products that are stored in Firebase Realtime Database. When user ask my bot for status then Firebase function get data from DB and then send back Telegram message for every of product that the user is assigned. For some users this can take some time even 2 minutes.
When 1st user asks bot for status and bot function run for the first time everything is fine.
BUT when 2nd user ask for status during first call of bot function (when function still running for 1st user) first call run start over and after first call is done finally second call are handled.
When 3rd user calls function when old calls are not finished, everything stacking on and finally everything loops until all calls of function are over. Because bot has almost 2000 active users this above problem runs into "infinite" loop because constantly some of users calls "status" for themselves.
This situation causes that users getting almost infinite numbers of messages.
I'm using JavaScript & Node 12 on Firebase.
const { Telegraf, Markup } = require('telegraf');
const { telegrafThrottler } = require('telegraf-throttler');
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const debug = true;
admin.initializeApp(); // initialize firebase-admin
const bot = new Telegraf(functions.config().telegram_token.key); // initialize Telegraf bot
const throttler = telegrafThrottler(); // Telegraf Throttler
bot.use(throttler);
/**
*
bot.command('some_commands_here', async (ctx) => {
const nothing = 'THIS IS NOT IMPORTANT';
});
bot.command(...) more commands
*/
/** action with infinite loop problem */
bot.action('status', async (ctx) => {
const uid = ctx.update.callback_query.from.id;
let userData = await getUserAccountData(admin, uid); // get some data from firebase realtime db
if (userData !== null) {
let userProducts = await getUserProducts(admin, uid); // get some data from firebase realtime db
if (userProducts !== null) {
// userProducts contain even 200 items for one user
for (const [privateProductId, privateProductData] of Object.entries(userProducts)) {
// some not important logic that create message and keyboard context
// after this bot send informations about every product (can be even 200 messages )
await bot.telegram.sendMessage(uid, `${message}`, {
parse_mode: 'html',
reply_markup: keyboard.reply_markup,
});
}
}
}
// some not important logic if userData / userProducts are null
});
/** Default response for undefinded msg/commands */
bot.on('message', (ctx) => ctx.reply("Use /help if You don't know commands!"));
/** bot catch errors here */
bot.catch((err, ctx) => {
if (debug) {functions.logger.error(`Bot Catched ERROR: ${err}`);}
bot.telegram.sendMessage(123456789, `Bot Catched ERROR: ${err}`);
});
const runtimeOpts = {
timeoutSeconds: 500,
memory: '1GB',
};
exports.bot = functions.region('europe-west3').runWith(runtimeOpts).https.onRequest((req, res) => {
// bot.handleUpdate(req.body, res);
bot.handleUpdate(req.body, res).catch((err) => {
if (debug) {functions.logger.error(err);}
});
});
OK Finally I found cause ^^
I'm missed process.once in my code, because of that function was executed more than one time.
process.once('SIGINT', () => bot.stop('SIGINT'));
process.once('SIGTERM', () => bot.stop('SIGTERM'));

Pushing query result from back end to front end with interval

I'm playing around with sockets for the first time and have a created a very simple back end and front end to test with our system at work.
I want the back end to query our server every 10 seconds in this example and pass the results to the front end.
I currently have the interval set as 10 seconds however when I run it I only get the result after ten seconds - i want the result straight away and then to check every ten seconds for changes.
I've tried moving code around and seeing what works, but I usually get a message telling me the variable is undefined (because it is then obviously outside the function.
My code is below - I am aware its probably a it overkill having the set interval in both the result and catch, so if anyone can help tidy it up so it works correctly, I'd appreciate it. Still a bit of a noob I'm afraid!
const express = require("express");
const app = express();
const server = require("http").createServer(app);
const io = require("socket.io")(server);
const oledb = require('oledb');
const smartconn =
`--myodbcconnection--`;
const db = oledb.odbcConnection(smartconn);
let command = `SELECT item FROM mytable.table LIMIT 10`
db.query(command)
.then(result => {
setInterval(function(){
io.emit("query", result.result);
}, 10000);
},
err => {
setInterval(function(){
io.emit("query", err);
}, 10000);
});
io.set("origins", "*:*");
io.on("connection", async (socket) => {
console.log("Client Successfully Connected");
});
server.listen(5000, () => {
console.log("Backend Server is running on http://localhost:5000");
});
Expect results to show immediately. Previously the old method didn't use sockets and polled the using set interval from the front end, which I want to move away from.
Here's one way to do it:
//Resolves a Promise after ms milliseconds
const sleep = (ms) => {
return new Promise((resolve, reject) => {
setTimeout(resolve, ms);
});
}
//Returns a db.query result with server status
const getServerStatus = async () => {
return await db.query(`SELECT item FROM mytable.table LIMIT 10`);
}
//Runs indefinitely and emits events to frontend every 10 seconds
(async () => {
while(true){
try{
const result = await getServerStatus();
io.emit("query", result.result);
} catch (error){
io.emit("query", error); //It would be better to change the event name to something else
}
await sleep(10000);
}
})();
This way the first event will be sent immediately because unlike setInterval, my implementation waits after executing the code, not before. Also, you can be sure that queries will not overlap when they take more than 10s to execute. setInterval doesn't guarantee that the next execution will wait for the previous one to finish.
The downside is that events will be sent after (10,000ms + query_delay), so depending on your database size and performance, some of them might get delayed by a few or a few hundred milliseconds. To counter that, you can measure getServerStatus's execution time and subtract it from the wait time.
Sorted it, by moving the emit functions into the io.on function.
Cheers!

How to implement a counter function using firebase functions?

I WANT TO IMPLEMENT A COUNTER FUNCTION USING FIREBASE FUNCTION TO COUNT NO OF TIMES MY APP IS BEING OPENED.
What I want:
Android app opened---> app calling ------>firebase function executed via http trigger------->firebase function increment value stored in firebase database
How to read and update data on firebase realtime database from firebase Functions.
I made an Firebase function which triggers on http triggers.
Code:
const functions = require('firebase-functions');
exports.counterFunction = functions.https.onRequest((request, response) => {
response.send("Hello from Firebase");
******Code to increment value in firebase database*********
});
I have a field in firebase realtime database called count and 0 corresponds to it
count : 0
I want to increment count variable every time the firebase function is executed
IN SHORT I WANT TO IMPLEMENT A COUNTER USING FIREBASE.
I just want to record the number of times my app started . So I am calling the Http Trigger function using http request using 'okhttp' and the function need to increment the count.
The following Firebase function example should help you understand how to write to the realtime database from a function
https://github.com/firebase/functions-samples/tree/3b41b2e04d854a821a0149e1e5b0769bad397d67/quickstarts/uppercase
Have also a look at https://firebase.google.com/docs/functions/get-started
You could try:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const app = admin.initializeApp();
exports.counterFunction = functions.https.onRequest((request, response) => {
response.send("Hello from Firebase");
return app.database().ref(`/count`).once('value', (snap) => {
const value = snap.val() || 0;
return app.database().ref(`/count`).set(value + 1).then(res => {
return true;
}).catch(err => {
return Promise.reject(err);
});
});
});
This will increment your counter each time your cloud function is executed.

Resources