from fastapi import FastAPI, HTTPException from fastapi.middleware.cors import CORSMiddleware from fastapi.staticfiles import StaticFiles from fastapi.responses import FileResponse from contextlib import asynccontextmanager import uvicorn import logging import os from pathlib import Path from app.routes import routes from app.db.database import init_db, SessionLocal from app.services.service_manager import ServiceManager # Configure logging log_file = Path("app.log") if log_file.exists(): # Archive old log file instead of deleting archive_path = log_file.with_suffix(f'.{log_file.stat().st_mtime}.log') log_file.rename(archive_path) # Create a formatter formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(name)s - %(message)s') # Create handlers console_handler = logging.StreamHandler() console_handler.setFormatter(formatter) file_handler = logging.FileHandler(log_file, mode='w', encoding='utf-8') file_handler.setFormatter(formatter) # Configure root logger root_logger = logging.getLogger() root_logger.setLevel(logging.DEBUG) root_logger.addHandler(console_handler) root_logger.addHandler(file_handler) # Get logger for this module logger = logging.getLogger(__name__) logger.info("Application starting up...") # Initialize service manager service_manager = None @asynccontextmanager async def lifespan(app: FastAPI): global service_manager service_manager = ServiceManager() # Startup try: init_db() logger.info("Database initialized successfully") # Initialize all services await service_manager.initialize_services() # Get a database session db = SessionLocal() try: data_init_service = service_manager.get_service('data_initialization') data_init = await data_init_service.initialize_data(db, game_ids=[1, 3], use_cache=True, init_categories=False, init_products=False, init_groups=False, init_archived_prices=False, init_mtgjson=False, archived_prices_start_date="2024-03-05", archived_prices_end_date="2025-04-17") logger.info(f"Data initialization results: {data_init}") # Start the scheduler scheduler = service_manager.get_service('scheduler') await scheduler.start_scheduled_tasks(db) logger.info("Scheduler started successfully") yield except Exception as e: logger.error(f"Error during application startup: {str(e)}") raise finally: db.close() except Exception as e: logger.error(f"Critical error during application startup: {str(e)}") raise finally: # Shutdown if service_manager: await service_manager.cleanup_services() logger.info("All services cleaned up successfully") app = FastAPI( title="CCR Cards Management API", description="API for managing CCR Cards Inventory, Orders, and more.", version="0.1.0", lifespan=lifespan ) # Mount static files directory app.mount("/static", StaticFiles(directory="app/static"), name="static") # Serve index.html at root @app.get("/") async def read_root(): index_path = Path('app/static/index.html') if not index_path.exists(): raise HTTPException(status_code=404, detail="Index file not found") return FileResponse(index_path) # Serve app.js @app.get("/app.js") async def read_app_js(): js_path = Path('app/static/app.js') if not js_path.exists(): raise HTTPException(status_code=404, detail="App.js file not found") return FileResponse(js_path) # Configure CORS with specific origins in production app.add_middleware( CORSMiddleware, allow_origins=["http://localhost:3000", "http://192.168.1.124:3000"], # Update with your frontend URL allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) app.include_router(routes.router) if __name__ == "__main__": uvicorn.run("app.main:app", host="0.0.0.0", port=8000, reload=True)