tdlib / telegram-bot-api

Telegram Bot API server
https://core.telegram.org/bots
Boost Software License 1.0
3.2k stars 601 forks source link

Callbacks Query Slowdowns (Rate limit?) #636

Open mircoianese opened 2 months ago

mircoianese commented 2 months ago

Hello,

I have a BOT with a lot of menus to interact with, and users are noticing slowdowns after they click a few buttons to navigate the menu.

It seems to me they are hitting some kind of Telegram rate limit (can't find it documented tho). I tested it (see the gif below) and indeed after 4-6 clicks the menu becomes unresponsive. If this is a rate limit, I think it should be increased a little bit as it's way too low in my opinion.

callbacks-lag

This also happens when using a local Telegram BOT API Server.

Sarisan commented 2 months ago

This is actually annoying, would like to have an option to disable it.

levlam commented 2 months ago

You can answer callback queries without any limits, so this is caused by the bot's code hanging up.

mircoianese commented 2 months ago

You can answer callback queries without any limits, so this is caused by the bot's code hanging up.

Not sure about that. The log you see on the left is on the entrypoint of my webhook, the updates are reaching the webhook out of order too when it becomes unresponsive. It seems to me those are not sent by telegram at all.

I will create a minimal example without the use of any external libraries to exclude issues with the library I’m using

mircoianese commented 2 months ago

The example above was in Java and had a webhook. I was able to reproduce the same exact issue with Python code on a much simpler BOT with updates listener:

from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import ApplicationBuilder, CommandHandler, CallbackQueryHandler

async def start(update: Update, context) -> None:
    keyboard = [
        [InlineKeyboardButton("Option 1", callback_data='1')],
        [InlineKeyboardButton("Option 2", callback_data='2')],
        [InlineKeyboardButton("Option 3", callback_data='3')],
        [InlineKeyboardButton("Option 4", callback_data='4')],
        [InlineKeyboardButton("Option 5", callback_data='5')],
        [InlineKeyboardButton("Option 6", callback_data='6')],
        [InlineKeyboardButton("Option 7", callback_data='7')],
        [InlineKeyboardButton("Option 8", callback_data='8')],
        [InlineKeyboardButton("Option 9", callback_data='9')],
        [InlineKeyboardButton("Option 10", callback_data='10')],
        [InlineKeyboardButton("Option 11", callback_data='11')],
    ]

    reply_markup = InlineKeyboardMarkup(keyboard)

    await update.message.reply_text(
        'Choose an option:',
        reply_markup=reply_markup
    )

# Handler to process callback data when a button is pressed
async def button(update: Update, context) -> None:
    query = update.callback_query
    print(f'Option: {query.data}')
    await query.answer()

# Main function to set up the bot
def main():
    application = ApplicationBuilder().token('<BOT_TOKEN>').build()

    application.add_handler(CommandHandler('start', start))
    application.add_handler(CallbackQueryHandler(button))

    application.run_polling(allowed_updates=Update.ALL_TYPES)

if __name__ == '__main__':
    main()

The result is basically the same: callbacks-lag-gif2

Sarisan commented 2 months ago

You can answer callback queries without any limits

Answer - yes, receive - no

levlam commented 2 months ago

@mircoianese Bot API server will not send multiple concurrent callback queries from the same user to webhook. Bot doesn't receive new queries, because it didn't answer the previous query.

mircoianese commented 2 months ago

@levlam This is not the case. I've added a print after the query.answer() method on the minimal example above. And, as you can see from the GIF below, the Option 5 Callback was correctly answered, but the Option 6 callback was not immediately received.

callbacks-lag-gif4

Here's the modified method:

async def button(update: Update, context) -> None:
    query = update.callback_query
    print(f'Option: {query.data}')
    await query.answer()
    print(f'Callback {query.data} answered.')

Please try to reproduce it and you will see this is a real issue, and it seems here I'm not the only one experiencing this. Thank you

levlam commented 2 months ago

Apps or server can also limit users if they try to send unreasonably many requests.

mircoianese commented 2 months ago

Apps or server can also limit users if they try to send unreasonably many requests.

Agree, but that does not seem to me a “unreasonable amount” of requests. I think this limit should be increased, or there should be a possibility to modify it if someone wants to allow an higher amount of callbacks queries per user to hit their server. Please consider this as an improvement, because right now navigating through menus using keyboards is almost frustrating.

levlam commented 2 months ago

The user must see and check result of the click. Current limits are high enough for that. If you want the user to be able to click as fast as possible without waiting for the result from the bot, you can consider to use a Mini App instead.

mircoianese commented 2 months ago

The user must see and check result of the click. Current limits are high enough for that. If you want the user to be able to click as fast as possible without waiting for the result from the bot, you can consider to use a Mini App instead.

In the last GIF I sent it can be clearly seen that the BOT is ANSWERING! But it's not receiving the subsequent Callback queries! So the user is not "waiting for the BOT to answer" - the BOT already answered. The Telegram server is not sending the updates, I'm 99% sure about that.

mircoianese commented 2 months ago

This is the last example I will send on why I think the current limits are not enough:

callbacks-lag5

Your choice to have this fixed or not.

levlam commented 2 months ago

The example shows that the limits are high enough. The user have no chance to read updated message content with the shown speed, hence they must be restricted from further queries.

mircoianese commented 2 months ago

The example shows that the limits are high enough. The user have no chance to read updated message content with the shown speed, hence they must be restricted from further queries.

A user that already knows the menu, and needs for example to navigate more menus to change only one setting, will hit the limit. I'm reporting it here because users are reporting it to me.

But yeah, if it's a problem to have it increased then it's ok... at least we agree that there's indeed a limit and it's not the bot hanging up.

levlam commented 2 months ago

The limit is even higher then the limit for editing messages in a given chat, hence there are no practical reasons to increase it.

carburano commented 2 months ago

+1. Very annoying problem

Sarisan commented 2 months ago

The limit is even higher then the limit for editing messages in a given chat, hence there are no practical reasons to increase it.

Then both limits shall be increased, it's no longer 2014 to keep it this low, hardware have been improved and people requirements have been increased as well.

mircoianese commented 2 months ago

I will throw here another simple example:

callbacks-lag6

In this menu users can navigate through daily deals: as you can see there is no need for the user to read the text, but he can immediately see from the link preview image if the product is interesting or not. In this case it becomes really hard to smoothly scroll the list and honestly, implementing it in MiniApp seems not a great solution but more like a workaround: you still have to bring the user "outside" of the BOT environment, which is not consistent with the user experience when using a BOT.

The only real (and correct) solution is to increase these insanely low limits.

levlam commented 2 months ago

@mircoianese The shown interfaces are very ineffective and inconvernient for the users. The button text doesn't fit, the other buttons are just cryptic emoji, and to do a basic action the user have to do many clicks and wait the bot to response. The whole interface can be done much better as a Mini app.

mircoianese commented 2 months ago

@mircoianese The shown interfaces are very ineffective and inconvernient for the users. The button text doesn't fit, the other buttons are just cryptic emoji, and to do a basic action the user have to do many clicks and wait the bot to response. The whole interface can be done much better as a Mini app.

User’s have documentation on what different buttons do. That’s not the point… the interface is not the point. Don’t try to don’t understand what the issue is. This is just ridiculous.

Again, this is your choice but I find this a really really easy problem to fix and it seems to me you just don’t wanna fix it.

Just close this issue if you don’t care… don’t even try to listen to what multiple different developers are trying to tell you