Files
Cerbero-mcp/src/cerbero_mcp/exchanges/sentiment/client.py
T
AdrianoDev 8ecc1a24a9 feat(V2): /health/ready con ping client + middleware request log strutturato + request_id correlation
- /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>
2026-05-01 09:03:28 +02:00

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"}