"""Shared outbound HTTP client factory. Deliberately plain: the default dual-stack resolver and a moderate timeout. History: v3.8.2 pinned outbound sockets to IPv4 (local_address="0.0.0.0") to chase a suspected IPv6 routing problem. Analytics writes had been succeeding before that change and stopped after it, so the pin is reverted. Forcing a local address can break egress in containerised hosts, and the original diagnosis was not supported by evidence: a 12s GET failed while an 8s POST to the same host succeeded, which rules out plain slowness. Set FORCE_IPV4_LOCAL_ADDRESS to "0.0.0.0" only to test that hypothesis again. """ import logging from typing import Optional import httpx logger = logging.getLogger(__name__) # None = let the OS choose (normal dual-stack behaviour). "0.0.0.0" forces IPv4. FORCE_IPV4_LOCAL_ADDRESS: Optional[str] = None DEFAULT_TIMEOUT = 10.0 def make_transport(retries: int = 1) -> httpx.AsyncHTTPTransport: kwargs = {"retries": retries} if FORCE_IPV4_LOCAL_ADDRESS: kwargs["local_address"] = FORCE_IPV4_LOCAL_ADDRESS try: return httpx.AsyncHTTPTransport(**kwargs) except Exception as exc: logger.warning(f"Custom transport unavailable ({exc}); using default") return httpx.AsyncHTTPTransport() def make_client(timeout: float = DEFAULT_TIMEOUT, retries: int = 1) -> httpx.AsyncClient: """AsyncClient with a moderate timeout and one transport-level retry.""" return httpx.AsyncClient( timeout=timeout, transport=make_transport(retries=retries), follow_redirects=True, )