Initial commit
This commit is contained in:
179
ui.py
Normal file
179
ui.py
Normal file
@@ -0,0 +1,179 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
ui.py - Main Application Entry Point and FastAPI App Initialization
|
||||
Orchestrates all components and initializes the FastAPI application
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
from typing import Dict, Any, Optional
|
||||
from pathlib import Path
|
||||
from fastapi import FastAPI, WebSocket
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
import uvicorn
|
||||
from dotenv import load_dotenv
|
||||
|
||||
# Import application modules
|
||||
from db import DatabaseManager
|
||||
from utils import load_config, setup_logging
|
||||
from main import BinanceDataCollector
|
||||
|
||||
# Import UI modules
|
||||
from ui_models import serialize_for_json
|
||||
from ui_routes import APIRoutes
|
||||
from ui_websocket import handle_websocket_connection, broadcast_status_updates, websocket_connections
|
||||
from ui_state import state_manager, get_current_status
|
||||
|
||||
# Load environment variables
|
||||
load_dotenv('variables.env')
|
||||
|
||||
# Setup logging
|
||||
setup_logging()
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Global application components
|
||||
app = FastAPI(
|
||||
title="Crypto Trading Data Collector",
|
||||
version="3.1.0",
|
||||
description="Real-time cryptocurrency market data collection and analysis platform"
|
||||
)
|
||||
|
||||
db_manager: Optional[DatabaseManager] = None
|
||||
data_collector: Optional[BinanceDataCollector] = None
|
||||
config: Dict[str, Any] = {}
|
||||
api_routes: Optional[APIRoutes] = None
|
||||
|
||||
# Add CORS middleware
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=["*"],
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
|
||||
@app.on_event("startup")
|
||||
async def startup_event():
|
||||
"""Initialize application on startup"""
|
||||
global db_manager, data_collector, config, api_routes
|
||||
|
||||
try:
|
||||
logger.info("=" * 80)
|
||||
logger.info("Starting Crypto Trading Data Collector v3.1.0")
|
||||
logger.info("=" * 80)
|
||||
|
||||
# Load configuration
|
||||
config = load_config()
|
||||
logger.info("✓ Configuration loaded successfully")
|
||||
|
||||
# Initialize database
|
||||
db_manager = DatabaseManager()
|
||||
await db_manager.initialize()
|
||||
logger.info("✓ Database initialized successfully")
|
||||
|
||||
# Initialize data collector
|
||||
data_collector = BinanceDataCollector()
|
||||
await data_collector.initialize()
|
||||
logger.info("✓ Data collector initialized successfully")
|
||||
|
||||
# Initialize API routes
|
||||
api_routes = APIRoutes(
|
||||
app,
|
||||
db_manager,
|
||||
data_collector,
|
||||
config,
|
||||
state_manager
|
||||
)
|
||||
logger.info("✓ API routes registered successfully")
|
||||
|
||||
# Restore collection state if it was running before reload
|
||||
if state_manager.get("is_collecting", False):
|
||||
logger.info("Restoring collection state from persistent storage...")
|
||||
try:
|
||||
await data_collector.start_continuous_collection()
|
||||
logger.info("✓ Collection state restored successfully")
|
||||
except Exception as e:
|
||||
logger.error(f"✗ Error restoring collection state: {e}")
|
||||
state_manager.update(is_collecting=False)
|
||||
|
||||
# Start WebSocket broadcaster
|
||||
async def status_getter():
|
||||
return await get_current_status(db_manager, data_collector, config)
|
||||
|
||||
asyncio.create_task(broadcast_status_updates(status_getter))
|
||||
logger.info("✓ WebSocket broadcaster started")
|
||||
|
||||
logger.info("=" * 80)
|
||||
logger.info("FastAPI application startup complete - Ready to serve requests")
|
||||
logger.info("=" * 80)
|
||||
|
||||
except Exception as e:
|
||||
logger.error("=" * 80)
|
||||
logger.error(f"FATAL ERROR during startup: {e}", exc_info=True)
|
||||
logger.error("=" * 80)
|
||||
raise
|
||||
|
||||
|
||||
@app.on_event("shutdown")
|
||||
async def shutdown_event():
|
||||
"""Clean shutdown"""
|
||||
global db_manager, data_collector
|
||||
|
||||
try:
|
||||
logger.info("=" * 80)
|
||||
logger.info("Shutting down Crypto Trading Data Collector")
|
||||
logger.info("=" * 80)
|
||||
|
||||
# Save current state before shutdown
|
||||
if data_collector:
|
||||
state_manager.update(
|
||||
is_collecting=data_collector.is_collecting if hasattr(data_collector, 'is_collecting') else False,
|
||||
websocket_collection_running=data_collector.websocket_collection_running if hasattr(data_collector, 'websocket_collection_running') else False
|
||||
)
|
||||
logger.info("✓ State saved")
|
||||
|
||||
# Close database connections
|
||||
if db_manager:
|
||||
try:
|
||||
await db_manager.close()
|
||||
logger.info("✓ Database connections closed")
|
||||
except Exception as e:
|
||||
logger.error(f"✗ Error closing database: {e}")
|
||||
|
||||
logger.info("=" * 80)
|
||||
logger.info("Shutdown complete")
|
||||
logger.info("=" * 80)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error during shutdown: {e}", exc_info=True)
|
||||
|
||||
|
||||
@app.websocket("/ws")
|
||||
async def websocket_endpoint(websocket: WebSocket):
|
||||
"""WebSocket endpoint for real-time updates"""
|
||||
await handle_websocket_connection(websocket)
|
||||
|
||||
|
||||
def main():
|
||||
"""Main entry point for running the application"""
|
||||
import os
|
||||
|
||||
# Get configuration from environment or use defaults
|
||||
host = os.getenv("WEB_HOST", "0.0.0.0")
|
||||
port = int(os.getenv("WEB_PORT", "8000"))
|
||||
reload = os.getenv("WEB_RELOAD", "False").lower() == "true"
|
||||
|
||||
logger.info(f"Starting server on {host}:{port} (reload={reload})")
|
||||
|
||||
uvicorn.run(
|
||||
"ui:app",
|
||||
host=host,
|
||||
port=port,
|
||||
reload=reload,
|
||||
log_level="info"
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Reference in New Issue
Block a user