Prevent Telegram polling handoffs and flood-control send failures
Telegram polling can inherit a stale webhook registration when a deployment switches transport modes, which leaves getUpdates idle even though the gateway starts cleanly. Outbound send also treats Telegram retry_after responses as terminal errors, so brief flood control can drop tool progress and replies. Constraint: Keep the PR narrowly scoped to upstream/main Telegram adapter behavior Rejected: Port OpenClaw's broader polling supervisor and offset persistence | too broad for an isolated fix PR Confidence: high Scope-risk: narrow Reversibility: clean Directive: Polling mode should clear webhook state before starting getUpdates, and send-path retry logic must distinguish flood control from timeouts Tested: uv run --extra dev pytest tests/gateway/test_telegram_* -q Not-tested: Live Telegram webhook-to-polling migration and real Bot API 429 behavior
This commit is contained in:
@@ -601,6 +601,12 @@ class TelegramAdapter(BasePlatformAdapter):
|
||||
)
|
||||
else:
|
||||
# ── Polling mode (default) ───────────────────────────
|
||||
# Clear any stale webhook first so polling doesn't inherit a
|
||||
# previous webhook registration and silently stop receiving updates.
|
||||
delete_webhook = getattr(self._bot, "delete_webhook", None)
|
||||
if callable(delete_webhook):
|
||||
await delete_webhook(drop_pending_updates=False)
|
||||
|
||||
loop = asyncio.get_running_loop()
|
||||
|
||||
def _polling_error_callback(error: Exception) -> None:
|
||||
@@ -856,6 +862,21 @@ class TelegramAdapter(BasePlatformAdapter):
|
||||
await asyncio.sleep(wait)
|
||||
else:
|
||||
raise
|
||||
except Exception as send_err:
|
||||
retry_after = getattr(send_err, "retry_after", None)
|
||||
if retry_after is not None or "retry after" in str(send_err).lower():
|
||||
if _send_attempt < 2:
|
||||
wait = float(retry_after) if retry_after is not None else 1.0
|
||||
logger.warning(
|
||||
"[%s] Telegram flood control on send (attempt %d/3), retrying in %.1fs: %s",
|
||||
self.name,
|
||||
_send_attempt + 1,
|
||||
wait,
|
||||
send_err,
|
||||
)
|
||||
await asyncio.sleep(wait)
|
||||
continue
|
||||
raise
|
||||
message_ids.append(str(msg.message_id))
|
||||
|
||||
return SendResult(
|
||||
|
||||
Reference in New Issue
Block a user