| """
|
| Главный файл FastAPI приложения для VK Mini App
|
| Поддержка Hugging Face Spaces
|
| """
|
| from fastapi import FastAPI
|
| from fastapi.middleware.cors import CORSMiddleware
|
| import logging
|
| import os
|
|
|
| from app.api.v1 import generate, health, vk
|
| from app.core.config import settings
|
| from app.core.redis import init_redis
|
|
|
|
|
| logging.basicConfig(
|
| level=logging.INFO,
|
| format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
| )
|
| logger = logging.getLogger(__name__)
|
|
|
|
|
| IS_HF_SPACE = os.getenv("SPACE_ID") is not None
|
| if IS_HF_SPACE:
|
| logger.info(f"🚀 Running on Hugging Face Space: {os.getenv('SPACE_ID')}")
|
| PORT = 7860
|
| else:
|
| PORT = settings.PORT
|
|
|
|
|
| app = FastAPI(
|
| title=settings.APP_NAME,
|
| description="AI Sudoku Generator for VK Mini Apps",
|
| version="1.0.0",
|
| docs_url="/docs",
|
| redoc_url="/redoc"
|
| )
|
|
|
|
|
| cors_origins = [
|
| "https://vk.com",
|
| "https://m.vk.com",
|
| "https://prod-app*.vkapps.ru",
|
| "http://localhost:3000",
|
| "http://localhost:8000",
|
| ]
|
|
|
|
|
| if IS_HF_SPACE and os.getenv("SPACE_ID"):
|
| space_url = f"https://{os.getenv('SPACE_ID')}.hf.space"
|
| cors_origins.append(space_url)
|
| logger.info(f"Added CORS origin: {space_url}")
|
|
|
|
|
| app.add_middleware(
|
| CORSMiddleware,
|
| allow_origins=cors_origins,
|
| allow_credentials=True,
|
| allow_methods=["*"],
|
| allow_headers=["*"],
|
| )
|
|
|
|
|
| app.include_router(generate.router, prefix=f"{settings.API_V1_PREFIX}/generate")
|
| app.include_router(vk.router, prefix=f"{settings.API_V1_PREFIX}/vk")
|
| app.include_router(health.router, prefix=settings.API_V1_PREFIX)
|
|
|
| @app.on_event("startup")
|
| async def startup_event():
|
| """Действия при запуске сервиса"""
|
| logger.info(f"🎮 Starting {settings.APP_NAME}...")
|
|
|
|
|
| if IS_HF_SPACE:
|
| logger.info("🏠 Environment: Hugging Face Space")
|
| else:
|
| logger.info("💻 Environment: Local Development")
|
|
|
|
|
| try:
|
| redis_client = await init_redis()
|
| if redis_client:
|
| logger.info("✅ Redis connected successfully")
|
| else:
|
| logger.info("ℹ️ Redis not available - running without cache")
|
| except Exception as e:
|
| logger.warning(f"⚠️ Redis connection failed: {e}")
|
|
|
|
|
| logger.info(f"📡 Service is running on port {PORT}")
|
| logger.info(f"📚 Documentation available at /docs")
|
| logger.info(f"🔍 Health check at /api/v1/health")
|
|
|
|
|
| logger.info(f"📊 Configuration:")
|
| logger.info(f" - Model: {settings.MODEL_NAME}")
|
| logger.info(f" - Difficulty levels: easy={settings.EMPTY_CELLS_EASY}, "
|
| f"medium={settings.EMPTY_CELLS_MEDIUM}, "
|
| f"hard={settings.EMPTY_CELLS_HARD}")
|
| logger.info(f" - CORS origins: {len(cors_origins)} configured")
|
|
|
| @app.on_event("shutdown")
|
| async def shutdown_event():
|
| """Действия при остановке сервиса"""
|
| logger.info("🛑 Shutting down...")
|
| try:
|
| from app.core.redis import close_redis
|
| await close_redis()
|
| logger.info("✅ Redis connection closed")
|
| except Exception as e:
|
| logger.warning(f"⚠️ Error closing Redis: {e}")
|
| logger.info("👋 Goodbye!")
|
|
|
| @app.get("/")
|
| async def root():
|
| """Корневой эндпоинт с информацией о сервисе"""
|
| return {
|
| "service": settings.APP_NAME,
|
| "status": "running",
|
| "version": "1.0.0",
|
| "environment": "huggingface" if IS_HF_SPACE else "local",
|
| "docs": "/docs",
|
| "health": "/api/v1/health",
|
| "generate": "/api/v1/generate/sudoku",
|
| "vk_integration": True,
|
| "endpoints": {
|
| "generate_sudoku": "POST /api/v1/generate/sudoku",
|
| "health_check": "GET /api/v1/health",
|
| "vk_user": "GET /api/v1/vk/user",
|
| "documentation": "/docs"
|
| }
|
| }
|
|
|
| @app.get("/health")
|
| async def simple_health():
|
| """Простой health check для мониторинга"""
|
| return {
|
| "status": "healthy",
|
| "environment": "huggingface" if IS_HF_SPACE else "local",
|
| "timestamp": __import__('time').time()
|
| }
|
|
|
|
|
| if __name__ == "__main__":
|
| import uvicorn
|
| port = 7860 if IS_HF_SPACE else settings.PORT
|
| uvicorn.run(
|
| "app.main:app",
|
| host=settings.HOST,
|
| port=port,
|
| reload=settings.DEBUG
|
| ) |