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:
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user