Skip to content

fix(telegram): require proven polling readiness on cold start#71118

Open
teknium1 wants to merge 4 commits into
mainfrom
fix/telegram-polling-readiness
Open

fix(telegram): require proven polling readiness on cold start#71118
teknium1 wants to merge 4 commits into
mainfrom
fix/telegram-polling-readiness

Conversation

@teknium1

Copy link
Copy Markdown
Contributor

Summary

The Telegram gateway no longer reports "connected" on hope — cold start requires a proven first getUpdates poll, and a silently-dead polling task now trips a deadline, disposes the adapter, and retries fresh instead of hanging at 'Connecting to Telegram (attempt 1/8)' forever with all threads idle.

Changes

  • plugins/platforms/telegram/adapter.py: generation-scoped getUpdates readiness gate on cold start (60s deadline, fail-closed → GatewayRunner disposes + retries a fresh adapter); wall-deadline bounds on deleteWebhook/start_polling (base: fix(telegram): require initial polling readiness #69240 by @mannnrachman, authorship preserved)
  • gateway/run.py: 180s Telegram outer connect budget (other platforms keep 30s; env override wins)
  • Regression tests for the threads-idle shape: polling task dies silently → error surfaced + retry (not an infinite wait)

Validation

Before After
First poll dies in shielded scope connected-but-deaf, hangs at attempt 1/8 60s deadline → dispose → fresh retry, visible in logs
Targeted suites 141 passed, 0 failed (48 readiness + 93 telegram/reconnect)

Distinct from the merged #70988 (frozen-loop watchdog) and #70987 (reconnect wedge) — this is the startup-readiness gap.

Fixes #67498

Infographic

telegram-polling-readiness

mannnrachman and others added 4 commits July 24, 2026 18:08
Use wall deadlines for deleteWebhook and start_polling, then fail cold startup unless getUpdates proves progress. This lets the gateway discard partial PTB state and retry with a fresh adapter.\n\nRefs #67498
Give Telegram a 180s default outer connect budget so cold polling can prove getUpdates readiness. Preserve the 30s default for other platforms and all explicit config/env overrides.\n\nRefs #67498
…neration

Follow-up hardening for the salvaged #69240 readiness gate (#67498):

- _start_polling_once now returns its (generation, progress_event) pair
  so the strict cold-start gate binds to exactly the generation it
  started, instead of re-reading self._polling_progress_event which a
  concurrent recovery task may have replaced with a newer generation's
  event (the G1/G2 race flagged in the #69240 review).
- Strict cold start no longer schedules background polling recovery: a
  polling error during the readiness wait is captured by a strict
  callback and fails the connect attempt immediately with a loud
  OSError, so GatewayRunner disposes the partial adapter and retries
  with a fresh one — no more waiting out the full readiness deadline on
  a generation that already errored, and no G2-on-partial-app healing.
- After readiness is proven the strict callback delegates every later
  polling error to the real background-recovery callback, preserving
  the existing degraded/reconnect semantics for the polling lifetime.
- The readiness-timeout error message now states the deadline and that
  the gateway will retry with a fresh adapter (loud failure, not a
  silent wait).
- Regression tests: current-generation progress connects; a polling
  error during strict cold start fails fast without scheduling
  background recovery (the #67498 idle-threads shape); stale-generation
  progress is rejected.

Progresses #67498
The strict cold-start readiness gate (#67498) means adapter.connect() no
longer returns True until the mocked start_polling records a successful
getUpdates round trip for its generation. Update the conflict-suite
Application mocks accordingly:

- fake_start_polling side effects call
  adapter._record_polling_progress(adapter._polling_generation) on the
  initial connect (retry generations intentionally do NOT auto-progress
  where a test asserts the conflict count survives an unproven retry).
- _build_polling_app takes the adapter so its start_polling mock can
  record progress.

Without this, the cold connects in these tests wait out the full 60s
readiness deadline and fail — which is exactly the fail-closed behavior
the gate is supposed to provide when polling shows no progress.
@github-actions

github-actions Bot commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

૮ >ﻌ< ა ci review

ran on 1b203d2

all good!

@alt-glitch alt-glitch added type/bug Something isn't working P1 High — major feature broken, no workaround comp/gateway Gateway runner, session dispatch, delivery comp/plugins Plugin system and bundled plugins platform/telegram Telegram bot adapter sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages labels Jul 25, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Related: this is the authorship-preserving successor to #69240, with the cold-start readiness gap distinct from the merged reconnect-wedge and frozen-loop work in #70987 and #70988.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/gateway Gateway runner, session dispatch, delivery comp/plugins Plugin system and bundled plugins P1 High — major feature broken, no workaround platform/telegram Telegram bot adapter sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages type/bug Something isn't working

Projects

None yet

3 participants