File size: 1,600 Bytes
04fb378
 
041c1c7
04fb378
041c1c7
 
 
 
 
 
 
 
04fb378
 
 
 
 
 
 
 
041c1c7
 
 
 
04fb378
 
041c1c7
 
 
 
04fb378
041c1c7
 
 
 
 
 
 
 
04fb378
041c1c7
04fb378
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
"""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,
    )