feat:新增大屏存取发布接口
This commit is contained in:
+58
@@ -1,6 +1,7 @@
|
||||
"""FastAPI 应用入口"""
|
||||
|
||||
import asyncio
|
||||
import re
|
||||
from contextlib import asynccontextmanager
|
||||
|
||||
from fastapi import Depends, FastAPI
|
||||
@@ -8,10 +9,15 @@ from loguru import logger
|
||||
|
||||
from app.api.agent import router
|
||||
from app.api.conversations import router as conversation_router
|
||||
from app.api.datasource import router as datasource_router
|
||||
from app.api.files import UploadSizeLimit
|
||||
from app.api.files import limits_router as file_limits_router
|
||||
from app.api.files import router as file_router
|
||||
from app.api.materials import router as material_router
|
||||
from app.api.public import router as public_router
|
||||
from app.api.screens import router as screen_router
|
||||
from app.config import settings
|
||||
from app.core.body_limit import BodyLimit, BodyLimitRule
|
||||
from app.core.auth import get_current_user
|
||||
from app.core.exceptions import register_exception_handlers
|
||||
from app.core.logging import setup_logging
|
||||
@@ -32,12 +38,16 @@ async def lifespan(application: FastAPI):
|
||||
from app.services.agent import AgentService
|
||||
from app.services.material_mongo import warm_material_cache
|
||||
from app.services.persistence import open_persistence
|
||||
from app.services.screen_mongo import MongoScreenStore
|
||||
from app.services.screens import ScreenService
|
||||
from app.services.thumbnails import ThumbnailStorage
|
||||
|
||||
# 按配置选择 MongoDB 或进程内存,会话记录与图检查点使用同一种存储
|
||||
persistence = await open_persistence()
|
||||
application.state.conversation_store = persistence.store
|
||||
mcp_processes = []
|
||||
sweeper = None
|
||||
trash_sweeper = None
|
||||
data_files = None
|
||||
try:
|
||||
# 数据文件的元数据和会话记录用同一种存储;启动时先清理一遍过期目录,之后每小时一次
|
||||
@@ -48,6 +58,21 @@ async def lifespan(application: FastAPI):
|
||||
)
|
||||
application.state.data_file_service = data_files
|
||||
sweeper = asyncio.create_task(data_files.run_sweeper())
|
||||
# 大屏存取必须落 MongoDB:没配时不创建服务,screens 相关接口返回 503,而不是存在内存里重启就丢
|
||||
screen_service = None
|
||||
if persistence.db is not None:
|
||||
screen_store = MongoScreenStore(persistence.db)
|
||||
await screen_store.ensure_indexes()
|
||||
screen_service = ScreenService(
|
||||
screen_store,
|
||||
ThumbnailStorage(settings.thumbnail_dir),
|
||||
data_files,
|
||||
settings.trash_retention_days,
|
||||
)
|
||||
trash_sweeper = asyncio.create_task(screen_service.run_trash_sweeper())
|
||||
else:
|
||||
logger.warning("未配置 MONGODB_URI,大屏存取接口不可用")
|
||||
application.state.screen_service = screen_service
|
||||
# 物料目录启动时载入内存,动作校验与前端接口共用,避免重复查询数据库
|
||||
await warm_material_cache(persistence.db)
|
||||
# 拉起 mcp_servers.json 中由应用管理的服务;单个服务失败只记录,用到它的请求执行时报错
|
||||
@@ -64,6 +89,8 @@ async def lifespan(application: FastAPI):
|
||||
finally:
|
||||
if sweeper is not None:
|
||||
sweeper.cancel()
|
||||
if trash_sweeper is not None:
|
||||
trash_sweeper.cancel()
|
||||
if data_files is not None:
|
||||
await data_files.aclose()
|
||||
# 共享客户端只在应用退出时关闭,追踪刷新放到线程避免阻塞事件循环
|
||||
@@ -102,6 +129,37 @@ def create_app() -> FastAPI:
|
||||
# 上传在读请求体之前先按 Content-Length 检查大小
|
||||
application.add_middleware(UploadSizeLimit, path=f"/api{file_router.prefix}")
|
||||
application.include_router(material_router, prefix="/api")
|
||||
application.include_router(screen_router, prefix="/api", dependencies=authenticated)
|
||||
application.include_router(
|
||||
datasource_router, prefix="/api", dependencies=authenticated
|
||||
)
|
||||
# 匿名接口统一放 /api/public 下,不挂鉴权
|
||||
application.include_router(public_router, prefix="/api")
|
||||
# 保存 / 发布的请求体比普通接口大得多,单独放宽;封面图 1 MB
|
||||
application.add_middleware(
|
||||
BodyLimit,
|
||||
rules=[
|
||||
BodyLimitRule(
|
||||
frozenset({"POST", "PUT"}),
|
||||
re.compile(r"/api/screens(/[^/]+)?"),
|
||||
settings.screen_max_mb * 1024 * 1024,
|
||||
f"大屏数据不能超过 {settings.screen_max_mb} MB",
|
||||
),
|
||||
BodyLimitRule(
|
||||
frozenset({"PUT"}),
|
||||
re.compile(r"/api/screens/[^/]+/thumbnail"),
|
||||
1024 * 1024 + 64 * 1024,
|
||||
"封面图不能超过 1 MB",
|
||||
),
|
||||
# 其余带请求体的接口(发布、复制、改名、数据源取数、会话)都只有几个字段
|
||||
BodyLimitRule(
|
||||
frozenset({"POST", "PUT", "PATCH"}),
|
||||
re.compile(r"/api/(screens|datasource|conversations)(/.*)?"),
|
||||
64 * 1024,
|
||||
"请求体过大",
|
||||
),
|
||||
],
|
||||
)
|
||||
return application
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user