Comments (23)
@HeySreelal Yes, I will use my own fork of this library locally, waiting this issue to be solved (or PR applied). I came to Dart from NodeJS and I don't want to return there. I appreciate your suggestion and I saved your lib in favourites.
If I said the ego thing is because @DinoLeung first reaction is to said it was my error, that I was doing polling requests, ... Even If you are bussy I think that it is not acceptable. But no problem, I will do it by my own.
from teledart.
@busslina it does not look like it's a bug, the error message shows that you are using the long pull method and TeleDart is trying to retry. Please check your API key and make sure it's valid.
from teledart.
@DinoLeung Do you know how can I do to prevent my whole app crashes? Because is an unhandled exception. Maybe a configuration argument or a try catch. But it seems that if it can be resolved with try catch it has to be in your lib code (because as you can see in the StackTrace, there are no trace of my code in order to put try catch clause).
Maybe I'm missing something
from teledart.
@busslina it does not look like it's a bug, the error message shows that you are using the long pull method and TeleDart is trying to retry. Please check your API key and make sure it's valid.
My Bot Token Api is 100% valid. It has been working okay before and after that crash.
The only thing I think that I could done wrong is to have a older version of Teledart. Now I'm using the latest
from teledart.
@busslina it does not look like it's a bug, the error message shows that you are using the long pull method and TeleDart is trying to retry. Please check your API key and make sure it's valid.
My Bot Token Api is 100% valid. It has been working okay before and after that crash.
The only thing I think that I could done wrong is to have a older version of Teledart. Now I'm using the latest
Sorry @busslina there's was indeed some updates to the file long_polling.dart
recently, but I'm not sure it has fixed anything particularly. Please monitor the issue. The error telegram thrown was pretty clear that the server is making too many requests to the API, therefore they temporarily block the client until the cool down period has past. it might not necessarily caused by the the recursive long poll, it could be some other part of the application spamming the server and appeared to throw errors when getting updates.
from teledart.
@DinoLeung I'm sorry too, but I firmly think that is caused by your lib (maybe corrected in the newer versions) because I don't comunicate with telegram api. I only use your lib to initiate the bot, some little configurations by using setMyCommands
method once. The rest is only managed by your lib to listen new messages & commands. I will attach my file to be clear.
Also, the hour at what happend the crash last night (2AM) indicates the error source: the long polling. I reviewed the server log and zero activity happend in the whole night.
The solution I think of is a) Restart my server every time crashes (via Systemd unit file) or modify your lib to catch that error (but I won't do that).
I understand that is not your fault if it works for two months in a row and suddenly it fail like this. Maybe is Telegram disturbing, I don't know, but the error is pretty clear: #0 LongPolling._onRecursivePollingHttpError (package:teledart/src/teledart/fetch/long_polling.dart> https://github.com/DinoLeung/TeleDart/pull/1 LongPolling._recursivePolling. (package:teledart/src/teledart/fetch/long_pol>
and is there where patch must be done (if not yet done).
Well, if that happen again with the latest version, I will just follow the error stack trace, put in there a try/catch and send a PR.
My code:
class TelegramBot {
// Data
final ConfigBase config;
late final TeleDart bot;
final List<MessageHandler> commandMiddlewares;
final List<BotCommand> commandList;
final List<MessageHandler> messageHandlers;
final bool listenToMessages;
/// Constructor.
TelegramBot({
required this.config,
required this.commandMiddlewares,
required this.commandList,
required this.messageHandlers,
required this.listenToMessages,
});
// Functions
//
// - 01 - Start
// - 02 - On message
// - 03 - On command
// - 04 - Send message
//#region
/// 01 - Start.
Future<void> start() async {
final username = (await Telegram(config.botToken).getMe()).username;
bot = TeleDart(config.botToken, Event(username!));
await _configurate();
bot.start();
// Listen to to messages (async)
if (listenToMessages) {
// (async) -- Messages
bot.onMessage().forEach(onMessage).catchError(_onReceivingError);
// (async) -- Commands
bot.onCommand().forEach(onCommand).catchError(_onReceivingError);
}
}
/// 02 - On message.
Future<void> onMessage(teledart.TeleDartMessage message) async {
// Execute handlers cascade
for (final handler in messageHandlers) {
// Execute handler
if (!await handler(message)) {
// Break cascade
return;
}
}
}
/// 03 - On command.
Future<void> onCommand(teledart.TeleDartMessage message) async {
// [01]: Execute middleware handlers cascade
for (final middleware in commandMiddlewares) {
// Execute middleware
if (!await middleware(message)) {
// Break cascade
return;
}
}
// [02]: Routing to match command (if any)
final command = _parseCommand(message.text!);
// message.text
for (final botCommand in commandList) {
// Check match
if (!botCommand.checkMatch(command)) {
continue;
}
// Executing command handler
await botCommand.handler(message);
return;
}
}
/// 04 - Send message.
Future<teledart.Message?> sendMessage(
int chatId,
String message, {
bool debug = true,
}) async {
try {
return await bot.sendMessage(chatId, message);
} catch (e) {
_onSendingError(e, debug: debug);
return null;
}
}
//#endregion
// Private functions
//
// - 01 - Configurate
// - 02 - On receiving error
// - 03 - On sending error
// - 04 - Parse command
//#region
/// 01 - Configurate.
Future<void> _configurate() async {
// [01]: My commands
if (!await bot.setMyCommands(commandList.map((e) => e.command).toList())) {
clib.error('TelegramBot._configurate() -- Error setting my commands');
}
}
/// 02 - On receiving error.
FutureOr<dynamic> _onReceivingError(Object error) async {
lib.debug(
'TelegramBot._onReceivingError() -- Error type: ${error.runtimeType} -- Error: $error');
}
/// 03 - On sending error.
void _onSendingError(
Object error, {
bool debug = true,
}) async {
lib.debug(
'TelegramBot._onSendingError() -- Error type: ${error.runtimeType} -- Error: $error',
active: debug);
}
/// 04 - Parse command.
String _parseCommand(String command) {
var ret = command.trim().split(' ').first.replaceFirst('/', '');
// Removing bot username
final index = ret.indexOf('@');
if (index != -1) {
ret = ret.substring(0, index);
}
return ret;
}
//#endregion
}
from teledart.
It happend again, now with the latest version of Teledart. I don't want to bother you but I think you are not being logically/scientifically with this issue. The error is very clear (package:teledart/src/teledart/fetch/long_polling.dart:113) and in return you are saying that the error is in my code (it would be the best case for me, because I would have fix it yet).
Same scenario that last time. 2 AM, server almost sleeping (like me)... and crash. Long polling file, line 113.
I'm sorry about my language but I don't understand your first reaction of "echar balones fuera (throw balls out)" like we say in Spain, while the error is pretty clear.
Thank you
LongPollingException: HttpClientException: 429 Too Many Requests: retry after 5
Jan 21 02:10:10 ip-xxx-xx-xx-xxx bash[54133]: #0 LongPolling._onRecursivePollingHttpError (package:teledart/src/teledart/fetch/long_polling.dart:113:7)
Jan 21 02:10:10 ip-xxx-xx-xx-xxx bash[54133]: #1 LongPolling._recursivePolling. (package:teledart/src/teledart/fetch/long_polling.d>
from teledart.
@busslina it does not look like it's a bug, the error message shows that you are using the long pull method and TeleDart is trying to retry. Please check your API key and make sure it's valid.
I'm not using the long polling method. I'm using your Library which uses the long polling method. So it is up to you (to your Library) to provide a way to catch the HTTP 429 failure status code and prevent the whole app to crash. Don't you agree?
from teledart.
I propose you a patch with this PR: #229
from teledart.
Hey @busslina and @DinoLeung, I was investigating this issue. From the logs @busslina shared I'm pretty sure that the long polling with the library is actually failing. But not sure why this issue is not appearing on a regular scale.
What I came up with is a wild guess that the Telegram servers start sending 429 errors when around 5-30 requests per second occur. On faster servers where the developer's code is deployed, the _recursivePolling
could easily reach this limit with the current implementation - which is basically one request right after the other is finished.
Maybe we should add a lil bit of wait time like at least a 200ms delay till the next _recursivePolling()
call.
Note: The 200ms is my simple calculation as 1000 / 5.
from teledart.
Oh well, I didn't see that PR. Unfortunately, I don't think a constant 5-second delay is needed whenever this 429 issue occurs. Instead, there's obviously a retry_after
parameter sent by Telegram servers with the error. That'd be much better if you're actually planning to write an auto-retry setup.
from teledart.
Hey @busslina and @DinoLeung, I was investigating this issue. From the logs @busslina shared I'm pretty sure that the long polling with the library is actually failing. But not sure why this issue is not appearing on a regular scale.
What I came up with is a wild guess that the Telegram servers start sending 429 errors when around 5-30 requests per second occur. On faster servers where the developer's code is deployed, the
_recursivePolling
could easily reach this limit with the current implementation - which is basically one request right after the other is finished.Maybe we should add a lil bit of wait time like at least a 200ms delay till the next
_recursivePolling()
call.Note: The 200ms is my simple calculation as 1000 / 5.
I think you are 100% right.
from teledart.
Oh well, I didn't see that PR. Unfortunately, I don't think a constant 5-second delay is needed whenever this 429 issue occurs. Instead, there's obviously a
retry_after
parameter sent by Telegram servers with the error. That'd be much better if you're actually planning to write an auto-retry setup.
Yes, I saw that retry_after header in 429 HTTP error, but as you can see here (https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/429) this header is not mandatory to be included.
I will update my PR to include the reading of this header and if it exists, await for that amount of time and if it does not exists then await 2500 ms.
Thank you
from teledart.
This type of error happens in any library and is due to connections with telegram itself.
I have several BOTs and they all have these issues occasionally. This already happened when I was in Ruby (I migrated everything to Dart).
What I do in all of them, to avoid problems, is to run a .sh script
#!/bin/sh
while [ 1 ]; of
gives you
./mybot
done
That way I never have problems.
from teledart.
@paulobreim Your solution is like mine: reboot after fail. But it is not an acceptable solution if a more specific solution can be done.
from teledart.
Now it comes the funny thing. Last night it crashed again and seeing the log I found it crashed at 02:10 AM, exactly the same hour the crash before (Jan. 21). So I looked for the first crash (the one that made me open this issue on Jan. 16) and surprise... same hour.
January 16:
Jan 16 02:10:13 ip-xxx-xx-xx-xxx bash[6019]: Unhandled exception:
Jan 16 02:10:13 ip-xxx-xx-xx-xxx bash[6019]: LongPollingException: HttpClientException: 429 Too Many Requests: retry after 5
Jan 16 02:10:13 ip-xxx-xx-xx-xxx bash[6019]: #0 LongPolling._onRecursivePollingHttpError (package:teledart/src/teledart/fetch/long_polling.dart:114:7)
Jan 16 02:10:13 ip-xxx-xx-xx-xxx bash[6019]: #1 LongPolling._recursivePolling. (package:teledart/src/teledart/fetch/long_polling.da>
Jan 16 02:10:13 ip-xxx-xx-xx-xxx bash[6019]: #2 _rootRunUnary (dart:async/zone.dart:1399:47)
January 21:
Jan 21 02:10:10 ip-xxx-xx-xx-xxx bash[54133]: Unhandled exception:
Jan 21 02:10:10 ip-xxx-xx-xx-xxx bash[54133]: LongPollingException: HttpClientException: 429 Too Many Requests: retry after 5
Jan 21 02:10:10 ip-xxx-xx-xx-xxx bash[54133]: #0 LongPolling._onRecursivePollingHttpError (package:teledart/src/teledart/fetch/long_polling.dart:113:7)
Jan 21 02:10:10 ip-xxx-xx-xx-xxx bash[54133]: #1 LongPolling._recursivePolling. (package:teledart/src/teledart/fetch/long_polling.d>
Jan 21 02:10:10 ip-xxx-xx-xx-xxx bash[54133]: #2 _rootRunUnary (dart:async/zone.dart:1399:47)
January 23:
Jan 23 02:10:19 ip-xxx-xx-xx-xxx bash[84580]: Unhandled exception:
Jan 23 02:10:19 ip-xxx-xx-xx-xxx bash[84580]: LongPollingException: HttpClientException: 429 Too Many Requests: retry after 5
Jan 23 02:10:19 ip-xxx-xx-xx-xxx bash[84580]: #0 LongPolling._onRecursivePollingHttpError (package:teledart/src/teledart/fetch/long_polling.dart:113:7)
Jan 23 02:10:19 ip-xxx-xx-xx-xxx bash[84580]: #1 LongPolling._recursivePolling. (package:teledart/src/teledart/fetch/long_polling.d>
Jan 23 02:10:19 ip-xxx-xx-xx-xxx bash[84580]: #2 _rootRunUnary (dart:async/zone.dart:1399:47)
I randomly restart my server at random hours, I didn't had any server activity at the time those crashes happend, ...
The first thing that I could think about it is that Telegram servers do some routinary stuff at that hour and maybe send 429, even if TeleDart is respecting the limits.
@HeySreelal proposed to me to read the retry_after header. I did that and proposed a PR (#230)
Come on @DinoLeung, mistakes are human
from teledart.
Some times I have HttpClientException: 429 Too Many Request.
It is occurs when some user ask something and the answers are long and divide in peaces. I think that put a delay after each answer
This is a security impose by Telegram. There are no bug in the @DinoLeung's lib.
from teledart.
Some times I have HttpClientException: 429 Too Many Request. It is occurs when some user ask something and the answers are long and divide in peaces. I think that put a delay after each answer This is a security impose by Telegram. There are no bug in the @DinoLeung's lib.
We are drowning in a glass of water. To clarify:
-
Unhandled exception occurs when an error happens in an async block of code and this error is not catched either a) on the async block of code with try/catch or b) in the caller of this async block (function) with Future.catchError method.
(a) - https://dart.dev/guides/libraries/futures-error-handling#potential-problem-accidentally-mixing-synchronous-and-asynchronous-errors
(b) - https://api.dart.dev/be/175791/dart-async/Future/catchError.html -
In this particular case, unhandled exception occurs here:
LongPolling._onRecursivePollingHttpError (package:teledart/src/teledart/fetch/long_polling.dart:113:7
link. -
I'm not interested in say this is an @DinoLeung bug/error or Telegram's . Just act logically with the facts. And the facts are pretty clear. This is an Unhandled exception because @DinoLeung code do not await here.
-
The only way I can think of to prevent an app crashes using this library when this event (bug/error) happens is to handle in a different way. @DinoLeung is throwing an error here and If he would await all async code everyone could have caught that error by surrounding Bot.start method with a try/catch. He decided an other logic, and it is okay. His error is to throw exception when receives 429 HTTP. The better way is to wait some time and re-polling again (the solution I propose here). Easy my friends. It is all about logic.
-
Lets understand the whole thing/issue deeply before talking easy. Yes I'm a little bit tired of discussing such an easy thing. I propose a solution (maybe not the better one). If ego is an obstacle to accept things it is not my problem. I prefer to everyone have a better version of this library, even if this error does not affect everyone even once, because one day it can happen (just wait to 2 AM haha).
from teledart.
I totally agree with all the first 4 points. And I don't think ego is the problem here. He might already be working on many other things or even other parts of this library. I could see a lot of changes in the last few weeks. Well, we're all humans and have priorities.
Yeah, simply returning to an awaited future could solve this just as you said we could catch the error with a try-catch block.
Every library has its own problems and advantages. At this point you have choices like:
- You can edit the library code on your local machine and run it that
- Use another library.
I've always been a fan of good bot libraries. My personal best choice is grammy (which is a Telegram bot framework on Node.js) If you want to stick to Dart, choose one from the pub.dev. Eg: Televerse (my own production lol, just to overcome disabilities of other packages.)
from teledart.
I have 4 BOTs running.
Sometimes, errors like: LongPollingException or TimeoutException occur.
When this happens, it happens on ALL Bots at the same time, which indicates that it is something on the Telegram side and not on my application.
from teledart.
I have 4 BOTs running. Sometimes, errors like: LongPollingException or TimeoutException occur. When this happens, it happens on ALL Bots at the same time, which indicates that it is something on the Telegram side and not on my application.
Yes, I have deduced that when I realized that it was always crashing at same hour (02:10 AM CET). The point here is to not letting unexpected external behavior make your app crash. To understand that you must read and understand this Lib code. I resolved this issue here #230
@DinoLeung was causing the crash throwing that exception. With the new code (not accepted yet), instead of throwing that not manageable error, now it wait some amount of time and re-poll again.
from teledart.
Is this implemented in teledart: ^0.5.3 version?
I will change onde of the BOTs to see what happiness.
from teledart.
Is this implemented in teledart: ^0.5.3 version?
I will change onde of the BOTs to see what happiness.
No, it is not. It is implemented in a pending Pull Request (waiting to be accepted).
You can try this implementation using a local package (like I'm doing). You can try to download my fork repo (https://github.com/busslina/TeleDart) and use it in your app's pubspec.yaml file like in the example below:
My server didn't crash again. It was such an easy mistake. I don't understand how a good coder cannot accept it and correct it for the good of all its users.
from teledart.
Related Issues (20)
- Photo message not getting 'text' value if provided? HOT 2
- Remove usage of a sleep function HOT 1
- support for web app bot HOT 3
- Phone messages are not streamed to onMessage stream HOT 3
- Email messages are not streamed to onMessage stream HOT 1
- Url messages are not streamed to onMessage stream HOT 1
- I have problem with message.reply(welcomeMsg) on iOS when app in background and run as profile or release mode. Plz help to check and improve on this! HOT 5
- Update TeleDart to http ^1.0.0
- is it still working ? HOT 6
- Teledart Client HOT 1
- Send message to a topic
- Garbage collection? Memory increase HOT 1
- HttpClientException should be exported. HOT 1
- Editing the inlineKeyboard after an Inline request HOT 1
- OS error semaphore timeout HOT 1
- Forcing optional param to exist HOT 1
- onCallbackQuery not called HOT 2
- LongPollingException: HttpClientException: 409 Conflict HOT 2
- I'm having issue with teledart.onMessage(entityType: '*').listen((message) is not executing when running as Release and the app is in Background state for iOS HOT 1
- How to launch app in telegram because the provided example doesn't do so. Even it doesn't require the hosted website url anywhere. How i can fix this ? HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from teledart.