186 lines
6.1 KiB
Python
186 lines
6.1 KiB
Python
"""
|
|
Cosmo - Deep Space Explorer Backend API
|
|
FastAPI application entry point
|
|
"""
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
# Add backend directory to Python path for direct execution
|
|
backend_dir = Path(__file__).resolve().parent.parent
|
|
if str(backend_dir) not in sys.path:
|
|
sys.path.insert(0, str(backend_dir))
|
|
|
|
import logging
|
|
from contextlib import asynccontextmanager
|
|
from fastapi import FastAPI
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
from fastapi.staticfiles import StaticFiles
|
|
|
|
from app.config import settings
|
|
from app.api.auth import router as auth_router
|
|
from app.api.user import router as user_router
|
|
from app.api.system import router as system_router
|
|
from app.api.danmaku import router as danmaku_router
|
|
from app.api.task import router as task_router
|
|
from app.api.cache import router as cache_router
|
|
from app.api.celestial_static import router as celestial_static_router
|
|
from app.api.celestial_body import router as celestial_body_router
|
|
from app.api.celestial_resource import router as celestial_resource_router
|
|
from app.api.celestial_orbit import router as celestial_orbit_router
|
|
from app.api.nasa_download import router as nasa_download_router
|
|
from app.api.celestial_position import router as celestial_position_router
|
|
from app.api.star_system import router as star_system_router
|
|
from app.services.redis_cache import redis_cache
|
|
from app.services.cache_preheat import preheat_all_caches
|
|
from app.database import close_db
|
|
|
|
# Configure logging
|
|
# Set root logger to WARNING in production, INFO in development
|
|
log_level = logging.INFO if settings.jwt_secret_key == "your-secret-key-change-this-in-production" else logging.WARNING
|
|
logging.basicConfig(
|
|
level=log_level,
|
|
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
|
)
|
|
|
|
# Reduce noise from specific loggers in production
|
|
if log_level == logging.WARNING:
|
|
logging.getLogger("app.services.cache").setLevel(logging.ERROR)
|
|
logging.getLogger("app.services.redis_cache").setLevel(logging.ERROR)
|
|
logging.getLogger("app.api.celestial_position").setLevel(logging.WARNING)
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
@asynccontextmanager
|
|
async def lifespan(app: FastAPI):
|
|
"""Application lifespan manager - startup and shutdown events"""
|
|
# Startup
|
|
logger.info("=" * 60)
|
|
logger.info("Starting Cosmo Backend API...")
|
|
logger.info("=" * 60)
|
|
|
|
# Connect to Redis
|
|
await redis_cache.connect()
|
|
|
|
# Initialize database tables (create if not exist)
|
|
from app.database import engine, Base
|
|
from app.models.db import SystemSettings # Import to register the model
|
|
async with engine.begin() as conn:
|
|
await conn.run_sync(Base.metadata.create_all)
|
|
logger.info("✓ Database tables initialized")
|
|
|
|
# Initialize default system settings
|
|
from app.database import AsyncSessionLocal
|
|
from app.services.system_settings_service import system_settings_service
|
|
async with AsyncSessionLocal() as db:
|
|
await system_settings_service.initialize_default_settings(db)
|
|
await db.commit()
|
|
logger.info("✓ Default system settings initialized")
|
|
|
|
# Preheat caches (load from database to Redis)
|
|
await preheat_all_caches()
|
|
|
|
logger.info("✓ Application started successfully")
|
|
logger.info("=" * 60)
|
|
|
|
yield
|
|
|
|
# Shutdown
|
|
logger.info("=" * 60)
|
|
logger.info("Shutting down Cosmo Backend API...")
|
|
|
|
# Disconnect Redis
|
|
await redis_cache.disconnect()
|
|
|
|
# Close database connections
|
|
await close_db()
|
|
|
|
logger.info("✓ Application shutdown complete")
|
|
logger.info("=" * 60)
|
|
|
|
|
|
# Create FastAPI app
|
|
app = FastAPI(
|
|
title=settings.app_name,
|
|
description="Backend API for deep space probe visualization using NASA JPL Horizons data",
|
|
version="1.0.0",
|
|
lifespan=lifespan,
|
|
)
|
|
|
|
# Configure CORS
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=settings.cors_origins,
|
|
allow_credentials=True,
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
)
|
|
|
|
# Include routers
|
|
app.include_router(auth_router, prefix=settings.api_prefix)
|
|
app.include_router(user_router, prefix=settings.api_prefix)
|
|
app.include_router(system_router, prefix=settings.api_prefix)
|
|
app.include_router(danmaku_router, prefix=settings.api_prefix)
|
|
|
|
# Celestial body related routers
|
|
app.include_router(star_system_router, prefix=settings.api_prefix)
|
|
app.include_router(celestial_body_router, prefix=settings.api_prefix)
|
|
app.include_router(celestial_position_router, prefix=settings.api_prefix)
|
|
app.include_router(celestial_resource_router, prefix=settings.api_prefix)
|
|
app.include_router(celestial_orbit_router, prefix=settings.api_prefix)
|
|
app.include_router(celestial_static_router, prefix=settings.api_prefix)
|
|
|
|
# Admin and utility routers
|
|
app.include_router(cache_router, prefix=settings.api_prefix)
|
|
app.include_router(nasa_download_router, prefix=settings.api_prefix)
|
|
app.include_router(task_router, prefix=settings.api_prefix)
|
|
|
|
# Mount static files for uploaded resources
|
|
upload_dir = Path(__file__).parent.parent / "upload"
|
|
upload_dir.mkdir(exist_ok=True)
|
|
app.mount("/upload", StaticFiles(directory=str(upload_dir)), name="upload")
|
|
logger.info(f"Static files mounted at /upload -> {upload_dir}")
|
|
|
|
# Mount public assets directory
|
|
public_assets_dir = Path(__file__).parent.parent / "public" / "assets"
|
|
public_assets_dir.mkdir(parents=True, exist_ok=True)
|
|
app.mount("/public/assets", StaticFiles(directory=str(public_assets_dir)), name="public_assets")
|
|
logger.info(f"Public assets mounted at /public/assets -> {public_assets_dir}")
|
|
|
|
|
|
@app.get("/")
|
|
async def root():
|
|
"""Root endpoint"""
|
|
return {
|
|
"app": settings.app_name,
|
|
"version": "1.0.0",
|
|
"docs": "/docs",
|
|
"api": settings.api_prefix,
|
|
}
|
|
|
|
|
|
@app.get("/health")
|
|
async def health():
|
|
"""Health check endpoint with service status"""
|
|
from app.services.redis_cache import redis_cache
|
|
|
|
redis_stats = await redis_cache.get_stats()
|
|
|
|
return {
|
|
"status": "healthy",
|
|
"redis": redis_stats,
|
|
"database": "connected", # If we got here, database is working
|
|
}
|
|
|
|
|
|
if __name__ == "__main__":
|
|
import uvicorn
|
|
|
|
uvicorn.run(
|
|
"app.main:app",
|
|
host="0.0.0.0",
|
|
port=8000,
|
|
reload=True,
|
|
log_level="info",
|
|
)
|