Paweł Mioduszewski
Paweł Mioduszewski

Reputation: 95

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);}
    });
});

Upvotes: 0

Views: 1888

Answers (1)

Paweł Mioduszewski
Paweł Mioduszewski

Reputation: 95

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'));

Upvotes: 4

Related Questions