D
D
den94ka2018-11-05 15:28:14
PHP
den94ka, 2018-11-05 15:28:14

How to limit the number of requests per second in a Telegram bot?

Good afternoon.
I have a Telegram bot that gives out bonuses to people. The bonus is issued once a day. In order to receive a bonus, you need to click on the button (it doesn't matter if it's inline or regular). And now cunning people press the button dozens of times in a few seconds and receive not one, but several bonuses as a result.
The function that handles the click looks something like this:

1. Проверить, когда начислялся бонус последний раз
2. Если больше дня назад, то начислить бонус и обновить дату получения

That is, only 2-3 commands, there can be no errors in them, they are banal and I checked them a hundred times.
If you press normally, that is, at least with a pause of a few seconds (without hammering the mouse button), then the function works correctly and calculates only once, and at other times it displays an error (they say the bonus has already been received). But if you press a million times (conditionally) in seconds, then the accrual occurs several times (as if it does not have time to be processed).
The bot is written in PHP. I thought about recording the date of the user's last access to the bot in the database, but I'm afraid that it won't work either, just like the bonus accrual function.
And since Telegram sends all requests from its API, it will not work to limit them through the server settings.

Answer the question

In order to leave comments, you need to log in

7 answer(s)
B
Boris Korobkov, 2018-11-05
@BorisKorobkov

You should not "limit the number of requests", but study what the "race condition" is.

V
VadosL, 2018-11-06
@VadosL

I also noticed such a feature of behavior on bots written in Python. But there, most likely, the point is that the updater scatters the processing of incoming updates across threads, and this is where the race condition occurs. Can you look in this direction?

A
Artyom Innokentiev, 2018-11-06
@artinnok

Put the user ID in Redis and put EX for a day :)
When you receive a request for a bonus, check the presence of the user ID in Redis using EXISTS - if not, then you did not receive it within a day. If there is - then received within a day.

M
Mysterion, 2018-11-05
@Mysterion

It is trite to add a parameter to the session and check its presence.
Before processing the click, set it and check it before accessing the database.
Check, for example, the current date, the date of the last access and calculate the difference in the required amount of time.

I
Ivan Shumov, 2018-11-05
@inoise

Take a queue, let's say RabbitMQ or Kafka. Hang a send handler on the other end and let it check before sending how many messages it sent in the last second. If the limit is exhausted then cooldown. This, of course, will turn out to be a narrow neck, but for most tasks it should be enough. It’s not really necessary to parallel this story because the limits there are not high, but if you really want to, I can suggest completely wild options

O
Oleg, 2018-11-05
@OlegPyatakov

Options:

  • Implement something like a mutex for the bonus accrual function
  • Make a single-threaded queue or use an external one
  • Make a delay in accruals: by pressing the button, an application for accrual is made, and the bonus is then accrued to everyone who pressed the button

A
Adamos, 2018-11-06
@Adamos

1. Check when the bonus was last accrued
2. If more than a day ago, then accrue the bonus and update the date of receipt

If the bonuses are stored in the database, then you just need to combine these two actions into one atomic update statement.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question