Files
item_bank/app/main.py
T
2026-08-01 16:50:55 +08:00

79 lines
2.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""FastAPI 应用入口。"""
import logging
from contextlib import asynccontextmanager
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from slowapi import _rate_limit_exceeded_handler
from slowapi.errors import RateLimitExceeded
from slowapi.middleware import SlowAPIMiddleware
from app.api import (
ai,
auth,
images,
jobs,
notebook,
questions,
settings as settings_api,
tags,
)
from app.config import settings
from app.db import Base, engine
from app.ratelimit import limiter
from app.services.startup import fail_stale_jobs
# 确保所有模型被导入注册到 metadata
import app.models # noqa: F401
logger = logging.getLogger(__name__)
@asynccontextmanager
async def lifespan(app: FastAPI):
# 公网暴露,配置有问题就别启动了,免得带着弱密钥上线
problems = settings.check_production_secrets()
if problems:
for p in problems:
logger.error("配置错误:%s", p)
raise RuntimeError("生产配置校验失败:" + "".join(problems))
# 仅开发环境自动建表,方便快速迭代;生产用 Alembic 迁移(见 deploy/
if settings.debug:
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
# BackgroundTasks 不跨重启,把残留的进行中任务标记为失败,
# 否则前端会对着永不完成的任务无限轮询
await fail_stale_jobs()
yield
app = FastAPI(title=settings.app_name, lifespan=lifespan)
# 限流:超限返回 429
app.state.limiter = limiter
app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)
app.add_middleware(
CORSMiddleware,
allow_origins=settings.cors_origin_list,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
app.include_router(auth.router)
app.include_router(questions.router)
app.include_router(tags.router)
app.include_router(images.router)
app.include_router(jobs.router)
app.include_router(settings_api.router)
app.include_router(ai.router)
app.include_router(notebook.router)
@app.get("/api/health")
async def health():
return {"status": "ok"}