8ecc1a24a9
- /health/ready: ping di tutti i client (exchange, env) cached con timeout 2s, status ready|degraded|not_ready, opt-in 503 via READY_FAILS_ON_DEGRADED. - Middleware mcp.request: 1 riga JSON per HTTP request con request_id, method, path, status_code, duration_ms, actor, bot_tag, exchange, tool, client_ip, user_agent. - request_id propagato in request.state, audit log e error envelope per correlazione cross-cutting. - Aggiunto async health() come probe minimo a bybit/alpaca/macro/ sentiment/deribit (hyperliquid lo aveva già). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
28 lines
1.1 KiB
Python
28 lines
1.1 KiB
Python
"""SentimentClient: contenitore credenziali per data provider sentiment.
|
|
|
|
Sentiment è un read-only data provider (CryptoPanic, LunarCrush, aggregazioni
|
|
multi-exchange di funding/OI da endpoint pubblici). Nessun testnet/mainnet,
|
|
nessuna sessione HTTP persistente — i `fetchers.py` aprono client httpx ad-hoc
|
|
tramite `cerbero_mcp.common.http.async_client`. Questo wrapper esiste solo per
|
|
uniformità con il pattern degli altri exchange (DeribitClient/BybitClient/...)
|
|
e per essere istanziato dal `ClientRegistry`.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
|
|
class SentimentClient:
|
|
"""Wrapper credenziali CryptoPanic/LunarCrush. Stateless, no HTTP session."""
|
|
|
|
def __init__(self, *, cryptopanic_key: str = "", lunarcrush_key: str = "") -> None:
|
|
self.cryptopanic_key = cryptopanic_key
|
|
self.lunarcrush_key = lunarcrush_key
|
|
|
|
async def aclose(self) -> None: # pragma: no cover - no-op, no resources
|
|
return None
|
|
|
|
async def health(self) -> dict[str, Any]:
|
|
"""Probe minimo per /health/ready: nessuna chiamata di rete."""
|
|
return {"status": "ok"}
|