File size: 4,235 Bytes
a24b1f8 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
"""
Intelligent Provider API Router
Exposes intelligent load-balanced provider service
TRUE ROUND-ROBIN with health-based selection - No fake data!
"""
from fastapi import APIRouter, HTTPException, Query
from fastapi.responses import JSONResponse
from typing import List, Optional
import logging
from backend.services.intelligent_provider_service import get_intelligent_provider_service
logger = logging.getLogger(__name__)
router = APIRouter(prefix="/api/providers", tags=["Intelligent Providers"])
@router.get("/market-prices")
async def get_market_prices(
symbols: Optional[str] = Query(None, description="Comma-separated list of symbols (e.g., BTC,ETH,BNB)"),
limit: int = Query(100, ge=1, le=250, description="Number of results to return")
):
"""
Get market prices with intelligent load balancing
Features:
- TRUE round-robin distribution across ALL providers
- Each provider goes to back of queue after use
- Health-based selection (avoids failed providers)
- Automatic exponential backoff on failures
- Provider-specific caching
**NO FAKE DATA - All data from real APIs only!**
"""
try:
service = get_intelligent_provider_service()
# Parse symbols
symbol_list = None
if symbols:
symbol_list = [s.strip().upper() for s in symbols.split(',')]
# Get prices with intelligent load balancing
result = await service.get_market_prices(symbols=symbol_list, limit=limit)
return JSONResponse(content={
"success": True,
"data": result['data'],
"meta": {
"source": result['source'],
"cached": result.get('cached', False),
"timestamp": result['timestamp'],
"count": len(result['data']),
"error": result.get('error')
}
})
except Exception as e:
logger.error(f"Error fetching market prices: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.get("/stats")
async def get_provider_stats():
"""
Get statistics for all providers
Returns:
- Current queue order
- Provider health and load scores
- Success/failure rates
- Backoff status
- Cache statistics
"""
try:
service = get_intelligent_provider_service()
stats = service.get_provider_stats()
return JSONResponse(content={
"success": True,
"stats": stats
})
except Exception as e:
logger.error(f"Error fetching provider stats: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.get("/health")
async def health_check():
"""
Check health of intelligent provider service
"""
try:
service = get_intelligent_provider_service()
stats = service.get_provider_stats()
# Count available providers
available_count = sum(
1 for p in stats['providers'].values()
if p.get('is_available', False)
)
total_count = len(stats['providers'])
# Calculate total requests
total_requests = sum(
p.get('total_requests', 0)
for p in stats['providers'].values()
)
# Calculate average success rate
success_rates = [
p.get('success_rate', 0)
for p in stats['providers'].values()
]
avg_success_rate = sum(success_rates) / len(success_rates) if success_rates else 0
return JSONResponse(content={
"success": True,
"status": "healthy" if available_count > 0 else "degraded",
"available_providers": available_count,
"total_providers": total_count,
"cache_entries": stats['cache']['valid_entries'],
"total_requests": total_requests,
"avg_success_rate": round(avg_success_rate, 2),
"queue_order": stats['queue_order']
})
except Exception as e:
logger.error(f"Error checking health: {e}")
raise HTTPException(status_code=500, detail=str(e))
__all__ = ["router"]
|