Files

38 lines
1.1 KiB
Python

"""Shared pooled httpx.AsyncClient.
Hot paths (scrapers, Telegram send/poll, price feeds, X poster) used to build
a fresh AsyncClient per request, paying a TCP+TLS handshake every time. This
module owns one process-wide client with keep-alive pooling; callers override
the timeout per request (`client.get(url, timeout=10)`).
Lifecycle: lazily created on first use; main.py's lifespan closes it on
shutdown. Low-frequency daily jobs (KOL/macro fetchers) may keep their own
ad-hoc clients — pooling only matters on the per-second paths.
"""
import logging
from typing import Optional
import httpx
logger = logging.getLogger(__name__)
_client: Optional[httpx.AsyncClient] = None
def get_client() -> httpx.AsyncClient:
global _client
if _client is None or _client.is_closed:
_client = httpx.AsyncClient(
timeout=httpx.Timeout(20.0),
follow_redirects=True,
limits=httpx.Limits(max_connections=50, max_keepalive_connections=20),
)
return _client
async def aclose() -> None:
global _client
if _client is not None and not _client.is_closed:
await _client.aclose()
_client = None