58 lines
1.9 KiB
Python
58 lines
1.9 KiB
Python
"""Shared HTTP client factory for long-lived platform adapters.
|
|
|
|
Persistent ``httpx.AsyncClient`` pools amortise TLS setup, but httpx's default
|
|
``keepalive_expiry`` (5s) lets peer-initiated FIN sit in ``CLOSE_WAIT`` behind
|
|
transparent proxies (macOS + Cloudflare Warp) — multiplied across 7 adapters
|
|
plus LLM/MCP clients that walks into the default 256 fd limit (#18451).
|
|
``platform_httpx_limits()`` returns a tighter ``httpx.Limits``:
|
|
``max_keepalive_connections=10`` (platform APIs rarely parallelise beyond
|
|
this), ``keepalive_expiry=2.0`` (close idle sockets aggressively).
|
|
|
|
Override via ``HERMES_GATEWAY_HTTPX_KEEPALIVE_EXPIRY`` /
|
|
``HERMES_GATEWAY_HTTPX_MAX_KEEPALIVE`` env vars when tuning under load.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
|
|
try:
|
|
import httpx
|
|
except ImportError: # pragma: no cover — optional dep
|
|
httpx = None # type: ignore[assignment]
|
|
|
|
|
|
_DEFAULT_KEEPALIVE_EXPIRY_S = 2.0
|
|
_DEFAULT_MAX_KEEPALIVE = 10
|
|
|
|
|
|
def _positive_env(name: str, default, cast):
|
|
"""``cast(env)`` when set, parseable and > 0; else *default*."""
|
|
raw = os.environ.get(name, "").strip()
|
|
if not raw:
|
|
return default
|
|
try:
|
|
val = cast(raw)
|
|
except (TypeError, ValueError):
|
|
return default
|
|
return val if val > 0 else default
|
|
|
|
|
|
def platform_httpx_limits() -> "httpx.Limits | None":
|
|
"""``httpx.Limits`` tuned for persistent platform-adapter clients.
|
|
|
|
Returns ``None`` when httpx isn't importable so callers can fall back to
|
|
httpx's built-in default without a hard dependency on this helper.
|
|
"""
|
|
if httpx is None:
|
|
return None
|
|
return httpx.Limits(
|
|
max_keepalive_connections=_positive_env(
|
|
"HERMES_GATEWAY_HTTPX_MAX_KEEPALIVE", _DEFAULT_MAX_KEEPALIVE, int
|
|
),
|
|
# max_connections stays at the httpx default (100) — plenty of headroom.
|
|
keepalive_expiry=_positive_env(
|
|
"HERMES_GATEWAY_HTTPX_KEEPALIVE_EXPIRY", _DEFAULT_KEEPALIVE_EXPIRY_S, float
|
|
),
|
|
)
|