fix: retry Telegram requests on proxy timeouts

This commit is contained in:
MpakobecEx 2026-10-18 18:09:47 +05:00
parent d379be4bbd
commit 83a52bb88e
1 changed files with 53 additions and 15 deletions

68
bot.py
View File

@ -8,7 +8,7 @@ from pathlib import Path
from telegram import InputFile, Update
from telegram.constants import ChatAction, ChatType
from telegram.error import BadRequest, TelegramError
from telegram.error import BadRequest, NetworkError, TelegramError, TimedOut
from telegram.ext import (
Application,
CommandHandler,
@ -47,11 +47,11 @@ class MpakoBot:
builder = (
Application.builder()
.token(self._settings.bot_token)
.connect_timeout(10)
.read_timeout(30)
.write_timeout(30)
.get_updates_connect_timeout(10)
.get_updates_read_timeout(30)
.connect_timeout(20)
.read_timeout(60)
.write_timeout(60)
.get_updates_connect_timeout(20)
.get_updates_read_timeout(60)
.post_init(self._post_init)
.post_shutdown(self._post_shutdown)
)
@ -251,7 +251,15 @@ class MpakoBot:
await message.reply_text("Не удалось поставить задачу. Попробуй позже.")
return False
status_message = await message.reply_text(self._ack_text(position))
try:
status_message = await self._retry(
message.reply_text, self._ack_text(position)
)
except TelegramError:
logger.exception(
"Не удалось отправить подтверждение по запросу %s", request.id
)
return True
self._status_messages[request.id] = (
status_message.chat_id,
status_message.message_id,
@ -303,6 +311,23 @@ class MpakoBot:
event.error or "Не удалось сгенерировать изображение.",
)
async def _retry(self, func, *args, attempts: int = 3, **kwargs):
delay = 1.0
for attempt in range(1, attempts + 1):
try:
return await func(*args, **kwargs)
except (TimedOut, NetworkError):
if attempt >= attempts:
raise
logger.warning(
"Telegram timeout (%s/%s), повтор через %.0f с",
attempt,
attempts,
delay,
)
await asyncio.sleep(delay)
delay *= 2
async def _edit_status(
self,
request_id: int,
@ -328,7 +353,8 @@ class MpakoBot:
chat_id, message_id = target
try:
await self._bot.edit_message_text(
await self._retry(
self._bot.edit_message_text,
chat_id=chat_id,
message_id=message_id,
text=text,
@ -366,22 +392,26 @@ class MpakoBot:
await self._finish_failed(request, "Файл результата не читается.")
return
try:
await self._bot.send_photo(
await self._retry(
self._bot.send_photo,
chat_id=chat_id,
photo=InputFile(content, filename=filename),
caption=caption,
read_timeout=120,
write_timeout=120,
attempts=2,
)
except TelegramError:
logger.exception("Не удалось отправить фото по запросу %s", request.id)
try:
await self._bot.send_document(
await self._retry(
self._bot.send_document,
chat_id=chat_id,
document=InputFile(content, filename=filename),
caption=caption,
read_timeout=120,
write_timeout=120,
attempts=2,
)
except TelegramError:
await self._finish_failed(
@ -397,7 +427,8 @@ class MpakoBot:
text = f"Не получилось: {error}"
if target is not None and self._bot is not None:
try:
await self._bot.edit_message_text(
await self._retry(
self._bot.edit_message_text,
chat_id=target[0],
message_id=target[1],
text=text,
@ -406,7 +437,9 @@ class MpakoBot:
logger.debug("Не удалось показать ошибку по запросу %s", request.id)
if self._bot is not None:
try:
await self._bot.send_message(chat_id=chat_id, text=text)
await self._retry(
self._bot.send_message, chat_id=chat_id, text=text
)
except TelegramError:
logger.exception(
"Не удалось отправить ошибку по запросу %s", request.id
@ -416,7 +449,9 @@ class MpakoBot:
if self._bot is not None:
try:
await self._bot.send_message(chat_id=chat_id, text=text)
await self._retry(
self._bot.send_message, chat_id=chat_id, text=text
)
except TelegramError:
logger.exception("Не удалось отправить ошибку по запросу %s", request.id)
@ -425,8 +460,11 @@ class MpakoBot:
self._last_edit.pop(request_id, None)
if delete and target is not None and self._bot is not None:
try:
await self._bot.delete_message(
chat_id=target[0], message_id=target[1]
await self._retry(
self._bot.delete_message,
chat_id=target[0],
message_id=target[1],
attempts=2,
)
except TelegramError:
logger.debug("Не удалось удалить статус %s", request_id)