- Backend: FastAPI + SQLAlchemy + Celery (Python 3.11+) - Frontend: Vue 3 + TypeScript + Pinia + Tailwind - Admin Frontend: separate Vue 3 app for management - Docker Compose: 9 services orchestration - Specs: design prototypes, memory system PRD, product roadmap Cleanup performed: - Removed temporary debug scripts from backend root - Removed deprecated admin_app.py (embedded UI) - Removed duplicate docs from admin-frontend - Updated .gitignore for Vite cache and egg-info
81 lines
2.3 KiB
Python
81 lines
2.3 KiB
Python
from contextlib import asynccontextmanager
|
|
|
|
from fastapi import FastAPI
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
|
|
from app.api import (
|
|
auth,
|
|
memories,
|
|
profiles,
|
|
push_configs,
|
|
reading_events,
|
|
stories,
|
|
universes,
|
|
)
|
|
from app.core.config import settings
|
|
from app.core.logging import get_logger, setup_logging
|
|
from app.db.database import init_db
|
|
|
|
setup_logging()
|
|
logger = get_logger(__name__)
|
|
|
|
|
|
@asynccontextmanager
|
|
async def lifespan(app: FastAPI):
|
|
"""App lifespan manager."""
|
|
logger.info("app_starting", app_name=settings.app_name)
|
|
await init_db()
|
|
logger.info("database_initialized")
|
|
|
|
# 加载 provider 缓存
|
|
await _load_provider_cache()
|
|
|
|
yield
|
|
logger.info("app_shutdown")
|
|
|
|
|
|
async def _load_provider_cache():
|
|
"""启动时加载 provider 缓存。"""
|
|
from app.db.database import _get_session_factory
|
|
from app.services.provider_cache import reload_providers
|
|
|
|
try:
|
|
session_factory = _get_session_factory()
|
|
async with session_factory() as session:
|
|
cache = await reload_providers(session)
|
|
provider_count = sum(len(v) for v in cache.values())
|
|
logger.info("provider_cache_loaded", provider_count=provider_count)
|
|
except Exception as e:
|
|
logger.warning("provider_cache_load_failed", error=str(e))
|
|
# 不阻止启动,使用 settings 中的默认配置
|
|
|
|
|
|
app = FastAPI(
|
|
title=settings.app_name,
|
|
description="AI-driven story generator for kids.",
|
|
version="0.1.0",
|
|
lifespan=lifespan,
|
|
)
|
|
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=settings.cors_origins,
|
|
allow_credentials=True,
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
)
|
|
|
|
app.include_router(auth.router, prefix="/auth", tags=["auth"])
|
|
app.include_router(stories.router, prefix="/api", tags=["stories"])
|
|
app.include_router(profiles.router, prefix="/api", tags=["profiles"])
|
|
app.include_router(universes.router, prefix="/api", tags=["universes"])
|
|
app.include_router(push_configs.router, prefix="/api", tags=["push-configs"])
|
|
app.include_router(reading_events.router, prefix="/api", tags=["reading-events"])
|
|
app.include_router(memories.router, prefix="/api", tags=["memories"])
|
|
|
|
|
|
@app.get("/health")
|
|
async def health_check():
|
|
"""Simple liveness check."""
|
|
return {"status": "ok"}
|