fix(telegram): retry on transient TLS failures during connect and send (#1535)
fix(telegram): retry on transient TLS failures during connect and send
This commit is contained in:
commit
b411b979cb
1 changed files with 60 additions and 27 deletions
|
|
@ -202,8 +202,26 @@ class TelegramAdapter(BasePlatformAdapter):
|
||||||
self._handle_media_message
|
self._handle_media_message
|
||||||
))
|
))
|
||||||
|
|
||||||
# Start polling in background
|
# Start polling — retry initialize() for transient TLS resets
|
||||||
await self._app.initialize()
|
try:
|
||||||
|
from telegram.error import NetworkError, TimedOut
|
||||||
|
except ImportError:
|
||||||
|
NetworkError = TimedOut = OSError # type: ignore[misc,assignment]
|
||||||
|
_max_connect = 3
|
||||||
|
for _attempt in range(_max_connect):
|
||||||
|
try:
|
||||||
|
await self._app.initialize()
|
||||||
|
break
|
||||||
|
except (NetworkError, TimedOut, OSError) as init_err:
|
||||||
|
if _attempt < _max_connect - 1:
|
||||||
|
wait = 2 ** _attempt
|
||||||
|
logger.warning(
|
||||||
|
"[%s] Connect attempt %d/%d failed: %s — retrying in %ds",
|
||||||
|
self.name, _attempt + 1, _max_connect, init_err, wait,
|
||||||
|
)
|
||||||
|
await asyncio.sleep(wait)
|
||||||
|
else:
|
||||||
|
raise
|
||||||
await self._app.start()
|
await self._app.start()
|
||||||
loop = asyncio.get_running_loop()
|
loop = asyncio.get_running_loop()
|
||||||
|
|
||||||
|
|
@ -336,32 +354,47 @@ class TelegramAdapter(BasePlatformAdapter):
|
||||||
message_ids = []
|
message_ids = []
|
||||||
thread_id = metadata.get("thread_id") if metadata else None
|
thread_id = metadata.get("thread_id") if metadata else None
|
||||||
|
|
||||||
|
try:
|
||||||
|
from telegram.error import NetworkError as _NetErr
|
||||||
|
except ImportError:
|
||||||
|
_NetErr = OSError # type: ignore[misc,assignment]
|
||||||
|
|
||||||
for i, chunk in enumerate(chunks):
|
for i, chunk in enumerate(chunks):
|
||||||
# Try Markdown first, fall back to plain text if it fails
|
msg = None
|
||||||
try:
|
for _send_attempt in range(3):
|
||||||
msg = await self._bot.send_message(
|
try:
|
||||||
chat_id=int(chat_id),
|
# Try Markdown first, fall back to plain text if it fails
|
||||||
text=chunk,
|
try:
|
||||||
parse_mode=ParseMode.MARKDOWN_V2,
|
msg = await self._bot.send_message(
|
||||||
reply_to_message_id=int(reply_to) if reply_to and i == 0 else None,
|
chat_id=int(chat_id),
|
||||||
message_thread_id=int(thread_id) if thread_id else None,
|
text=chunk,
|
||||||
)
|
parse_mode=ParseMode.MARKDOWN_V2,
|
||||||
except Exception as md_error:
|
reply_to_message_id=int(reply_to) if reply_to and i == 0 else None,
|
||||||
# Markdown parsing failed, try plain text
|
message_thread_id=int(thread_id) if thread_id else None,
|
||||||
if "parse" in str(md_error).lower() or "markdown" in str(md_error).lower():
|
)
|
||||||
logger.warning("[%s] MarkdownV2 parse failed, falling back to plain text: %s", self.name, md_error)
|
except Exception as md_error:
|
||||||
# Strip MDV2 escape backslashes so the user doesn't
|
# Markdown parsing failed, try plain text
|
||||||
# see raw backslashes littered through the message.
|
if "parse" in str(md_error).lower() or "markdown" in str(md_error).lower():
|
||||||
plain_chunk = _strip_mdv2(chunk)
|
logger.warning("[%s] MarkdownV2 parse failed, falling back to plain text: %s", self.name, md_error)
|
||||||
msg = await self._bot.send_message(
|
plain_chunk = _strip_mdv2(chunk)
|
||||||
chat_id=int(chat_id),
|
msg = await self._bot.send_message(
|
||||||
text=plain_chunk,
|
chat_id=int(chat_id),
|
||||||
parse_mode=None, # Plain text
|
text=plain_chunk,
|
||||||
reply_to_message_id=int(reply_to) if reply_to and i == 0 else None,
|
parse_mode=None,
|
||||||
message_thread_id=int(thread_id) if thread_id else None,
|
reply_to_message_id=int(reply_to) if reply_to and i == 0 else None,
|
||||||
)
|
message_thread_id=int(thread_id) if thread_id else None,
|
||||||
else:
|
)
|
||||||
raise # Re-raise if not a parse error
|
else:
|
||||||
|
raise
|
||||||
|
break # success
|
||||||
|
except _NetErr as send_err:
|
||||||
|
if _send_attempt < 2:
|
||||||
|
wait = 2 ** _send_attempt
|
||||||
|
logger.warning("[%s] Network error on send (attempt %d/3), retrying in %ds: %s",
|
||||||
|
self.name, _send_attempt + 1, wait, send_err)
|
||||||
|
await asyncio.sleep(wait)
|
||||||
|
else:
|
||||||
|
raise
|
||||||
message_ids.append(str(msg.message_id))
|
message_ids.append(str(msg.message_id))
|
||||||
|
|
||||||
return SendResult(
|
return SendResult(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue