""" Sync API Router - Endpoints for data synchronization. """ from fastapi import APIRouter, BackgroundTasks, HTTPException from datetime import datetime from typing import List, Optional from src.schemas import SyncRequest, SyncResponse, SyncStatus from src.services.sync_service import SyncService router = APIRouter(prefix="/api/v1/sync", tags=["sync"]) # Singleton sync service sync_service = SyncService() @router.get("/status", response_model=SyncResponse) async def get_sync_status(): """Get current synchronization status.""" status = sync_service.get_status() return SyncResponse( status=SyncStatus(status.get("status", "idle")), message=status.get("message", ""), symbols_processed=status.get("symbols_processed", []), records_inserted=status.get("records_inserted", 0), errors=status.get("errors", []), started_at=status.get("started_at"), completed_at=status.get("completed_at") ) @router.post("/historical", response_model=SyncResponse) async def sync_historical( request: SyncRequest, background_tasks: BackgroundTasks ): """ Start historical data synchronization. This endpoint starts a background task to sync historical data from Polygon.io to the database. """ # Check if sync is already running current_status = sync_service.get_status() if current_status.get("status") == "running": raise HTTPException( status_code=409, detail="Sync already in progress" ) # Start sync in background background_tasks.add_task( sync_service.sync_all, symbols=request.symbols, start_date=request.start_date, end_date=request.end_date, timeframe=request.timeframe ) return SyncResponse( status=SyncStatus.pending, message="Historical sync started in background", symbols_processed=[], records_inserted=0, errors=[], started_at=datetime.now(), completed_at=None ) @router.post("/latest", response_model=SyncResponse) async def sync_latest( symbols: Optional[List[str]] = None, background_tasks: BackgroundTasks = None ): """ Sync latest data for all or specified tickers. This fetches the most recent data since the last sync. """ # Check if sync is already running current_status = sync_service.get_status() if current_status.get("status") == "running": raise HTTPException( status_code=409, detail="Sync already in progress" ) # Start sync in background background_tasks.add_task( sync_service.sync_all, symbols=symbols, start_date=None, # Will auto-detect from last timestamp end_date=None, timeframe="5m" ) return SyncResponse( status=SyncStatus.pending, message="Latest data sync started in background", symbols_processed=[], records_inserted=0, errors=[], started_at=datetime.now(), completed_at=None ) @router.post("/ticker/{symbol}", response_model=SyncResponse) async def sync_single_ticker( symbol: str, start_date: Optional[datetime] = None, end_date: Optional[datetime] = None, timeframe: str = "5m" ): """Sync data for a single ticker (synchronous).""" # This runs synchronously for single ticker result = await sync_service.sync_all( symbols=[symbol.upper()], start_date=start_date, end_date=end_date, timeframe=timeframe ) return SyncResponse( status=SyncStatus(result.get("status", "completed")), message=result.get("message", ""), symbols_processed=result.get("symbols_processed", []), records_inserted=result.get("records_inserted", 0), errors=result.get("errors", []), started_at=result.get("started_at"), completed_at=result.get("completed_at") )