chore: httpx retry transport + healthcheck stdlib + mypy config

- mcp_common/http.py: nuovo helper async_client() con
  AsyncHTTPTransport(retries=3) per gestire connection error transient
  + call_with_retry() generic async retry decorator. Sostituite 25
  occorrenze httpx.AsyncClient(...) in deribit/hyperliquid/sentiment/
  macro client. 5 nuovi test.

- Dockerfile healthcheck: passato da python+httpx subprocess a
  stdlib urllib.request.urlopen() su tutti i 6 servizi MCP. Zero
  dipendenze esterne nel runtime check, timeout esplicito 3s, image
  leggermente più snella.

- pyproject.toml: aggiunto [tool.mypy] python_version=3.13 con
  mypy_path multi-package + override ignore_missing_imports per i
  vendor SDK (pybit, alpaca, hyperliquid, pythonjsonlogger). mypy 1.20
  in dev deps; ruff pinned 0.5.x. mcp_common passa mypy clean; 44
  errori tipo pre-esistenti nei servizi affiorati ma non bloccanti —
  fix da pianificare separatamente.

- 455 test verdi.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
AdrianoDev
2026-04-28 07:26:17 +02:00
parent 4d9db750be
commit 6b7b3f7658
15 changed files with 395 additions and 53 deletions
+9 -8
View File
@@ -4,6 +4,7 @@ from datetime import UTC, datetime, timedelta
from typing import Any
import httpx
from mcp_common.http import async_client
FRED_BASE = "https://api.stlouisfed.org/fred/series/observations"
FINNHUB_CALENDAR = "https://finnhub.io/api/v1/calendar/economic"
@@ -79,7 +80,7 @@ async def fetch_asset_price(ticker: str) -> dict[str, Any]:
return {"ticker": ticker, "error": f"unknown ticker {ticker}"}
symbol, name = mapping
async with httpx.AsyncClient(timeout=10) as client:
async with async_client(timeout=10.0) as client:
info = await _fetch_yahoo_meta(client, symbol, "10d")
meta = info.get("meta") or {}
closes = info.get("closes") or []
@@ -129,7 +130,7 @@ async def fetch_treasury_yields() -> dict[str, Any]:
("us30y", "^TYX"),
]
yields: dict[str, float | None] = {}
async with httpx.AsyncClient(timeout=10) as client:
async with async_client(timeout=10.0) as client:
for key, sym in symbols:
info = await _fetch_yahoo_meta(client, sym, "5d")
meta = info.get("meta") or {}
@@ -217,7 +218,7 @@ async def fetch_breakeven_inflation(fred_api_key: str = "") -> dict[str, Any]:
"be_5y5y_forward": "T5YIFR",
}
out: dict[str, float | None] = {}
async with httpx.AsyncClient(timeout=10) as client:
async with async_client(timeout=10.0) as client:
for name, series_id in series_map.items():
resp = await client.get(
FRED_BASE,
@@ -270,7 +271,7 @@ async def fetch_equity_futures() -> dict[str, Any]:
session = "after-hours"
out: dict[str, Any] = {}
async with httpx.AsyncClient(timeout=10) as client:
async with async_client(timeout=10.0) as client:
for key, sym in tickers:
info = await _fetch_yahoo_meta(client, sym, "5d")
meta = info.get("meta") or {}
@@ -362,7 +363,7 @@ async def fetch_economic_indicators(
result: dict[str, Any] = {}
if not fred_api_key:
return {"indicators": result, "error": "No FRED API key configured"}
async with httpx.AsyncClient(timeout=10) as client:
async with async_client(timeout=10.0) as client:
for name, series_id in series_map.items():
if indicators and name not in indicators:
continue
@@ -444,7 +445,7 @@ async def fetch_macro_calendar(
# Try Forex Factory free feed first
try:
async with httpx.AsyncClient(timeout=10) as client:
async with async_client(timeout=10.0) as client:
resp = await client.get("https://nfs.faireconomy.media/ff_calendar_thisweek.json")
if resp.status_code == 200:
raw = resp.json()
@@ -503,7 +504,7 @@ async def fetch_macro_calendar(
try:
now = datetime.now(UTC)
end_default = now + timedelta(days=days_ahead)
async with httpx.AsyncClient(timeout=10) as client:
async with async_client(timeout=10.0) as client:
resp = await client.get(
FINNHUB_CALENDAR,
params={
@@ -571,7 +572,7 @@ async def fetch_market_overview() -> dict[str, Any]:
if _MARKET_CACHE["data"] is not None and (now - _MARKET_CACHE["ts"]) < _MARKET_CACHE_TTL:
return _MARKET_CACHE["data"]
async with httpx.AsyncClient(timeout=10) as client:
async with async_client(timeout=10.0) as client:
global_data: dict[str, Any] = {}
prices: dict[str, Any] = {}
try: