""" FastAPI Dependencies OrbiQuant IA Trading Platform - Data Service """ from typing import Optional, AsyncGenerator import asyncpg from fastapi import Request, HTTPException, status from config import Config async def get_db_pool(request: Request) -> asyncpg.Pool: """Get database connection pool from app state.""" pool = request.app.state.db_pool if not pool: raise HTTPException( status_code=status.HTTP_503_SERVICE_UNAVAILABLE, detail="Database connection not available" ) return pool async def get_db_connection(request: Request) -> AsyncGenerator[asyncpg.Connection, None]: """Get a database connection from pool.""" pool = await get_db_pool(request) async with pool.acquire() as connection: yield connection def get_data_service(request: Request): """Get DataService instance from app state.""" service = request.app.state.data_service if not service: raise HTTPException( status_code=status.HTTP_503_SERVICE_UNAVAILABLE, detail="Data service not initialized" ) return service def get_config(request: Request) -> Config: """Get configuration from app state.""" return request.app.state.config def get_polygon_client(request: Request): """Get Polygon client from app state.""" client = request.app.state.polygon_client if not client: raise HTTPException( status_code=status.HTTP_503_SERVICE_UNAVAILABLE, detail="Polygon client not configured" ) return client def get_mt4_client(request: Request): """Get MT4/MetaAPI client from app state.""" return request.app.state.mt4_client # May be None class RateLimiter: """Simple in-memory rate limiter.""" def __init__(self, requests_per_minute: int = 60): self.requests_per_minute = requests_per_minute self._requests: dict[str, list[float]] = {} async def check(self, client_id: str) -> bool: """Check if client can make a request.""" import time now = time.time() minute_ago = now - 60 if client_id not in self._requests: self._requests[client_id] = [] # Clean old requests self._requests[client_id] = [ ts for ts in self._requests[client_id] if ts > minute_ago ] if len(self._requests[client_id]) >= self.requests_per_minute: return False self._requests[client_id].append(now) return True # Global rate limiter instance rate_limiter = RateLimiter(requests_per_minute=60) async def check_rate_limit(request: Request) -> None: """Rate limit dependency.""" client_ip = request.client.host if request.client else "unknown" if not await rate_limiter.check(client_ip): raise HTTPException( status_code=status.HTTP_429_TOO_MANY_REQUESTS, detail="Too many requests. Please slow down." )