From a496c6da04cac1dfe3eacf5c94ecb76e4b124584 Mon Sep 17 00:00:00 2001 From: CI Bot Date: Fri, 28 Aug 2026 11:54:17 +0800 Subject: [PATCH] =?UTF-8?q?fix(from-assets):=20=E4=BF=AE=E5=A4=8DAI=20Code?= =?UTF-8?q?=20Review=E9=98=BB=E5=A1=9E=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 复用全局SessionLocal替代build_session_factory,避免每次创建新连接池 2. 分批获取所有片段替代硬编码limit=500,防止长模板截断 3. 初始化used_segments包含所有片段的当前随机时间,确保冲突检测正确 --- .../app/api/routes/templates_editor/clips.py | 36 ++++++++++++++----- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/apps/api/app/api/routes/templates_editor/clips.py b/apps/api/app/api/routes/templates_editor/clips.py index b678b9d15..5ee2946fb 100755 --- a/apps/api/app/api/routes/templates_editor/clips.py +++ b/apps/api/app/api/routes/templates_editor/clips.py @@ -690,16 +690,16 @@ def _update_mediakit_recommendations_async( # pragma: no cover 此函数在后台异步执行,不影响接口响应时间。 失败时静默处理,不影响已创建的片段。 """ - from app.config import settings - from packages.adapters.sqlalchemy_impl.asset_repository import SQLAlchemyAssetRepository - from packages.adapters.sqlalchemy_impl.session import build_session_factory + from packages.adapters.sqlalchemy_impl.session import SessionLocal db = None try: - # 创建独立的数据库 session(不复用请求 session) - _, session_factory = build_session_factory(settings.DATABASE_URL) - db = session_factory() + # 复用应用全局 Session(避免每次创建新连接池导致资源泄漏) + if SessionLocal is None: + logger.warning("后台任务: SessionLocal 未初始化,跳过 MediaKit 更新") + return + db = SessionLocal() # 初始化服务 asset_repo = SQLAlchemyAssetRepository(db) @@ -711,14 +711,32 @@ def _update_mediakit_recommendations_async( # pragma: no cover logger.info("后台任务: MediaKit 无推荐结果,跳过更新") return - # 查询该 plan 的所有片段 - clips = plan_svc.list_clips(plan_id, skip=0, limit=500) + # 查询该 plan 的所有片段(分批获取,避免硬编码 limit 截断) + batch_size = 500 + all_clips = [] + offset = 0 + while True: + batch = plan_svc.list_clips(plan_id, skip=offset, limit=batch_size) + if not batch: + break + all_clips.extend(batch) + if len(batch) < batch_size: + break + offset += batch_size + clips = all_clips + if not clips: logger.info("后台任务: plan_id=%s 无片段,跳过更新", plan_id) return - # 按 asset_id 分组,跟踪已使用时间段 + # 按 asset_id 分组,初始化已使用时间段(包含所有片段的当前随机时间) used_segments: dict[str, list[tuple[float, float]]] = {} + for clip in clips: + aid = getattr(clip, "asset_id", "") or "" + if aid and clip.start_time is not None: + used_segments.setdefault(aid, []).append( + (clip.start_time, clip.start_time + clip.duration) + ) # 遍历片段,按 asset_id 匹配推荐时间 for clip in clips: