"""PMFlow FastAPI 应用入口。""" from __future__ import annotations import os from contextlib import asynccontextmanager from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from .api.router import api_router from .core.config import settings from .core.logging import configure_logging, get_logger from .core.response import success_response from .database import AsyncSessionLocal, engine from .models import Base from .services.scheduler_center import WorkloadRecalcScheduler from .services.skill_service import init_system_skill_tags configure_logging(settings.debug) logger = get_logger(__name__) @asynccontextmanager async def lifespan(_: FastAPI): """应用生命周期:初始化表与系统技能标签。""" auto_create_tables = os.getenv("AUTO_CREATE_TABLES", "true").lower() in { "1", "true", "yes", } if auto_create_tables: async with engine.begin() as conn: await conn.run_sync(Base.metadata.create_all) async with AsyncSessionLocal() as db: try: created = await init_system_skill_tags(db, tenant_id=1) if created: logger.info("system_skill_tags_seeded", created=created) except Exception as exc: # pragma: no cover logger.warning("seed_system_skills_failed", error=str(exc)) scheduler = WorkloadRecalcScheduler(AsyncSessionLocal) scheduler.start() yield await scheduler.stop() await engine.dispose() app = FastAPI( title=settings.app_name, debug=settings.debug, version="0.1.0", lifespan=lifespan, ) origins = [item.strip() for item in settings.cors_origins.split(",") if item.strip()] app.add_middleware( CORSMiddleware, allow_origins=origins or ["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) app.include_router(api_router) @app.get("/healthz") async def healthz() -> dict: return success_response({"status": "ok"})