Telegram: harden network retries and config

Co-authored-by: techboss <techboss@users.noreply.github.com>
This commit is contained in:
Gustavo Madeira Santana
2026-01-26 19:24:13 -05:00
committed by Gustavo Madeira Santana
parent e43f4c0628
commit b861a0bd73
36 changed files with 457 additions and 61 deletions

View File

@@ -1,19 +1,36 @@
import { setDefaultAutoSelectFamily } from "net";
import * as net from "node:net";
import { resolveFetch } from "../infra/fetch.js";
import type { TelegramNetworkConfig } from "../config/types.telegram.js";
import { createSubsystemLogger } from "../logging/subsystem.js";
import { resolveTelegramAutoSelectFamilyDecision } from "./network-config.js";
// Workaround for Node.js 22 "Happy Eyeballs" (autoSelectFamily) bug
// that causes intermittent ETIMEDOUT errors when connecting to Telegram's
// dual-stack servers. Disabling autoSelectFamily forces sequential IPv4/IPv6
// attempts which works reliably.
let appliedAutoSelectFamily: boolean | null = null;
const log = createSubsystemLogger("telegram/network");
// Node 22 workaround: disable autoSelectFamily to avoid Happy Eyeballs timeouts.
// See: https://github.com/nodejs/node/issues/54359
try {
setDefaultAutoSelectFamily(false);
} catch {
// Ignore if not available (older Node versions)
function applyTelegramNetworkWorkarounds(network?: TelegramNetworkConfig): void {
const decision = resolveTelegramAutoSelectFamilyDecision({ network });
if (decision.value === null || decision.value === appliedAutoSelectFamily) return;
appliedAutoSelectFamily = decision.value;
if (typeof net.setDefaultAutoSelectFamily === "function") {
try {
net.setDefaultAutoSelectFamily(decision.value);
const label = decision.source ? ` (${decision.source})` : "";
log.info(`telegram: autoSelectFamily=${decision.value}${label}`);
} catch {
// ignore if unsupported by the runtime
}
}
}
// Prefer wrapped fetch when available to normalize AbortSignal across runtimes.
export function resolveTelegramFetch(proxyFetch?: typeof fetch): typeof fetch | undefined {
export function resolveTelegramFetch(
proxyFetch?: typeof fetch,
options?: { network?: TelegramNetworkConfig },
): typeof fetch | undefined {
applyTelegramNetworkWorkarounds(options?.network);
if (proxyFetch) return resolveFetch(proxyFetch);
const fetchImpl = resolveFetch();
if (!fetchImpl) {