diff --git a/gateway/platforms/telegram.py b/gateway/platforms/telegram.py index ac5b7fb8c..d8113eab0 100644 --- a/gateway/platforms/telegram.py +++ b/gateway/platforms/telegram.py @@ -518,6 +518,36 @@ class TelegramAdapter(BasePlatformAdapter): # Build the application builder = Application.builder().token(self.config.token) + + # PTB defaults (pool_timeout=1s) are too aggressive on flaky networks and + # can trigger "Pool timeout: All connections in the connection pool are occupied" + # during reconnect/bootstrap. Use safer defaults and allow env overrides. + def _env_int(name: str, default: int) -> int: + try: + return int(os.getenv(name, str(default))) + except (TypeError, ValueError): + return default + + def _env_float(name: str, default: float) -> float: + try: + return float(os.getenv(name, str(default))) + except (TypeError, ValueError): + return default + + request_kwargs = { + "connection_pool_size": _env_int("HERMES_TELEGRAM_HTTP_POOL_SIZE", 512), + "pool_timeout": _env_float("HERMES_TELEGRAM_HTTP_POOL_TIMEOUT", 8.0), + "connect_timeout": _env_float("HERMES_TELEGRAM_HTTP_CONNECT_TIMEOUT", 10.0), + "read_timeout": _env_float("HERMES_TELEGRAM_HTTP_READ_TIMEOUT", 20.0), + "write_timeout": _env_float("HERMES_TELEGRAM_HTTP_WRITE_TIMEOUT", 20.0), + } + + proxy_configured = any( + (os.getenv(k) or "").strip() + for k in ("HTTPS_PROXY", "HTTP_PROXY", "ALL_PROXY", "https_proxy", "http_proxy", "all_proxy") + ) + disable_fallback = (os.getenv("HERMES_TELEGRAM_DISABLE_FALLBACK_IPS", "").strip().lower() in ("1", "true", "yes", "on")) + fallback_ips = self._fallback_ips() if not fallback_ips: fallback_ips = await discover_fallback_ips() @@ -526,16 +556,32 @@ class TelegramAdapter(BasePlatformAdapter): self.name, ", ".join(fallback_ips), ) - if fallback_ips: + + if fallback_ips and not proxy_configured and not disable_fallback: logger.info( "[%s] Telegram fallback IPs active: %s", self.name, ", ".join(fallback_ips), ) - transport = TelegramFallbackTransport(fallback_ips) - request = HTTPXRequest(httpx_kwargs={"transport": transport}) - get_updates_request = HTTPXRequest(httpx_kwargs={"transport": transport}) - builder = builder.request(request).get_updates_request(get_updates_request) + # Keep request/update pools separate to reduce contention during + # polling reconnect + bot API bootstrap/delete_webhook calls. + request = HTTPXRequest( + **request_kwargs, + httpx_kwargs={"transport": TelegramFallbackTransport(fallback_ips)}, + ) + get_updates_request = HTTPXRequest( + **request_kwargs, + httpx_kwargs={"transport": TelegramFallbackTransport(fallback_ips)}, + ) + else: + if proxy_configured: + logger.info("[%s] Proxy configured; skipping Telegram fallback-IP transport", self.name) + elif disable_fallback: + logger.info("[%s] Telegram fallback-IP transport disabled via env", self.name) + request = HTTPXRequest(**request_kwargs) + get_updates_request = HTTPXRequest(**request_kwargs) + + builder = builder.request(request).get_updates_request(get_updates_request) self._app = builder.build() self._bot = self._app.bot