This commit is contained in:
amb
2026-09-01 13:00:36 +08:00
parent 1d8621717a
commit dfd38c99a0
35 changed files with 3141 additions and 21 deletions
+30 -6
View File
@@ -1,7 +1,7 @@
"""AI Knowledge Link — FastAPI 应用工厂。
Phase 1 只包含:配置校验、日志、异常处理器、健康检查、lifespan 资源管理。
后续 Phase 逐步挂载:auth、knowledge-bases、documents、public /k/ 路由。
Phase 1-3: 配置校验、日志、异常处理器、健康检查、lifespan 资源管理、认证路由
后续 Phase 逐步挂载:knowledge-bases、documents、public /k/ 路由。
"""
from contextlib import asynccontextmanager
@@ -10,15 +10,35 @@ from pathlib import Path
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from app.api.auth import router as auth_router
from app.api.documents import router as doc_router
from app.api.health import router as health_router
from app.api.knowledge_bases import router as kb_router
from app.public.routes import router as public_router
from app.core.config import get_settings
from app.core.db import dispose_engine
from app.core.db import dispose_engine, get_session_factory
from app.core.errors import register_exception_handlers
from app.core.logging import get_logger, setup_logging
logger = get_logger(__name__)
def _seed_free_plan() -> None:
"""启动时确保 free plan 存在(幂等)。"""
from app.repositories.plan_repo import PlanRepository
factory = get_session_factory()
with factory() as session:
repo = PlanRepository(session)
plan = repo.get_by_code("free")
if plan is None:
repo.get_or_create_free()
session.commit()
logger.info("Seeded free plan (100MB / 20MB-per-file)")
else:
logger.debug("Free plan already exists (id=%s)", plan.id)
@asynccontextmanager
async def lifespan(app: FastAPI):
settings = get_settings()
@@ -29,6 +49,9 @@ async def lifespan(app: FastAPI):
data_dir.mkdir(parents=True, exist_ok=True)
logger.info("Starting backend (env=%s, data=%s)", settings.environment, data_dir)
# Seed:确保 free plan 存在
_seed_free_plan()
yield
dispose_engine()
@@ -58,9 +81,10 @@ def create_app() -> FastAPI:
# 路由挂载
app.include_router(health_router, prefix="/api", tags=["health"])
# Phase 3+: app.include_router(auth_router, prefix="/api/auth", tags=["auth"])
# Phase 4+: app.include_router(kb_router, prefix="/api/knowledge-bases", tags=["knowledge-bases"])
# Phase 10+: app.include_router(public_router, tags=["public"])
app.include_router(auth_router, prefix="/api", tags=["auth"])
app.include_router(kb_router, prefix="/api", tags=["knowledge-bases"])
app.include_router(doc_router, prefix="/api", tags=["documents"])
app.include_router(public_router, tags=["public"])
return app