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