openclaw/docs/channels
Peter Steinberger 60fea81cf1
fix(telegram): harden polling transport liveness (#69476)
* fix(telegram): release undici dispatchers via TelegramTransport.close()

TelegramTransport now exposes an explicit close() that destroys every
owned undici dispatcher (default Agent plus lazily-created IPv4 and
IP-pinned fallback Agents) and the TCP sockets they hold. Dispatcher
constructors are also given bounded keep-alive defaults
(keepAliveTimeout, keepAliveMaxTimeout, connections, pipelining) as a
defence-in-depth layer so the pool cannot grow unbounded even if a
caller forgets to call close().

Without this, every transport that went through a fallback retry left
its fallback Agents anchored forever in a closure; long-running polling
sessions accumulated hundreds of ESTABLISHED keep-alive sockets to
api.telegram.org, saturating the per-IP quota on upstream forward
proxies and making the currently-active outbound node time out while
every other node still tested healthy.

Mock dispatchers in fetch.test.ts gain destroy() spies so the close()
chain is assertable. Call sites that built caller-owned transports from
globalThis.fetch (delivery.resolve-media, test helpers) return an async
no-op close(), matching the new required surface.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(telegram): dispose polling transport on shutdown and dirty rebuild

Every recoverable network error and stall-watchdog trip sets
TelegramPollingTransportState.#transportDirty so the next polling
cycle rebuilds the transport inside acquireForNextCycle(). Previously
the rebuild simply overwrote the field, leaving the old transport's
keep-alive sockets anchored in the now-unreferenced dispatcher — the
polling loop has no natural GC point for these resources, and Node's
object GC never touches OS-level sockets.

acquireForNextCycle() now closes the previous transport (fire-and-
forget so the polling cycle is not blocked by a slow destroy) before
swapping in the rebuilt one. dispose() is a new method that the owning
TelegramPollingSession calls from the finally block of runUntilAbort(),
so a single transport is always tied to a single polling session
lifetime. After dispose(), acquireForNextCycle() returns undefined to
prevent zombie rebuilds.

Under high sustained polling traffic over long-lived sessions, this is
what stops the per-gateway connection count to api.telegram.org from
growing indefinitely and saturating upstream proxy quotas.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(changelog): note Telegram undici dispatcher lifecycle fix

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(telegram): disable HTTP/2 for all Telegram polling dispatchers

Undici 8 enables HTTP/2 ALPN by default, but Telegram's long-polling
connections stall on Windows due to IPv6 + H2 multiplexing issues. The
core fetch-guard already sets allowH2:false for guarded paths, but the
Telegram extension creates its own Agent/ProxyAgent/EnvHttpProxyAgent
instances directly from undici without this flag.

Apply allowH2:false to all dispatcher constructors in the Telegram
transport layer, matching the approach used in src/infra/net/undici-runtime.ts.

Fixes #66885

* fix: avoid false telegram polling stall restarts

* fix(telegram): publish polling health liveness

---------

Co-authored-by: Ethan Chen <ethanbit@qq.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Magicray1217 <magicray1217@users.noreply.github.com>
Co-authored-by: aoao <aoao@openclaw>
2026-04-20 23:03:57 +01:00
..
bluebubbles.md fix(bluebubbles): configurable sendTimeoutMs, bump send default to 30s (#69193) 2026-04-20 10:04:52 -07:00
broadcast-groups.md
channel-routing.md
discord.md docs: cover 2026.4.7 changelog gaps 2026-04-08 07:26:56 +01:00
feishu.md feat: Streamline Feishu channel onboarding with QR code scan-to-create flow (#65680) 2026-04-13 18:03:44 +08:00
googlechat.md
group-messages.md Add /trace toggle and fix Active Memory diagnostics 2026-04-12 13:20:22 -05:00
groups.md docs: clarify optional Docker sandboxing 2026-04-20 19:27:45 +01:00
imessage.md
index.md docs: add WeChat channel guide 2026-04-18 18:26:40 +01:00
irc.md docs: update IRC host examples 2026-04-05 13:27:04 +01:00
line.md docs: refresh bundled channel naming mirrors 2026-04-04 15:16:11 +01:00
location.md
matrix.md fix(matrix): resolve live allowlist updates 2026-04-20 13:10:02 +01:00
mattermost.md docs: refresh bundled channel naming mirrors 2026-04-04 15:16:11 +01:00
msteams.md feat(msteams): add federated credential support (certificate + managed identity) (#53615) 2026-04-11 13:29:22 -05:00
nextcloud-talk.md docs: refresh bundled channel naming mirrors 2026-04-04 15:16:11 +01:00
nostr.md docs: refresh bundled channel plugin refs 2026-04-04 15:02:08 +01:00
pairing.md docs(pairing): explain approval upgrades 2026-04-20 13:08:04 +05:30
qa-channel.md feat: add one-command qa lab docker launcher 2026-04-06 17:47:17 +01:00
qqbot.md docs: refresh bundled channel ownership refs 2026-04-04 15:11:20 +01:00
signal.md
slack.md docs(slack): link to additional manifest settings 2026-04-11 23:47:43 -07:00
synology-chat.md docs: refresh bundled channel naming mirrors 2026-04-04 15:16:11 +01:00
telegram.md fix(telegram): harden polling transport liveness (#69476) 2026-04-20 23:03:57 +01:00
tlon.md docs: refresh bundled channel naming mirrors 2026-04-04 15:16:11 +01:00
troubleshooting.md fix(telegram): harden polling transport liveness (#69476) 2026-04-20 23:03:57 +01:00
twitch.md docs: refresh bundled channel naming mirrors 2026-04-04 15:16:11 +01:00
wechat.md docs: add WeChat channel guide 2026-04-18 18:26:40 +01:00
whatsapp.md refactor: share ambient proxy agent helpers 2026-04-06 15:03:30 +01:00
zalo.md docs: refresh bundled channel setup refs 2026-04-04 15:06:39 +01:00
zalouser.md docs: document shared mention policy 2026-04-07 07:51:00 +01:00