From 7ca80b5d0120a19b01ceeb47b0885aa154af5fed Mon Sep 17 00:00:00 2001 From: Timebomb2018 <18868801967@163.com> Date: Mon, 13 Apr 2026 18:52:43 +0800 Subject: [PATCH] perf(app): optimize FileMetadata queries by batching lookups Multiple services were performing individual database queries for FileMetadata when resolving missing file names/sizes. This change batches the queries using `in_()` to reduce database round trips and improve performance. --- api/app/services/app_chat_service.py | 30 ++++++++++++++++++++------- api/app/services/app_dsl_service.py | 2 +- api/app/services/draft_run_service.py | 15 ++++++++++---- 3 files changed, 34 insertions(+), 13 deletions(-) diff --git a/api/app/services/app_chat_service.py b/api/app/services/app_chat_service.py index 94362176..2d10ed44 100644 --- a/api/app/services/app_chat_service.py +++ b/api/app/services/app_chat_service.py @@ -219,13 +219,20 @@ class AppChatService: "reasoning_content": result.get("reasoning_content") } if files: + local_ids = [f.upload_file_id for f in files + if f.transfer_method.value == "local_file" and f.upload_file_id + and (not f.name or not f.size)] + meta_map = {} + if local_ids: + rows = self.db.query(FileMetadata).filter( + FileMetadata.id.in_(local_ids), + FileMetadata.status == "completed" + ).all() + meta_map = {str(r.id): r for r in rows} for f in files: name, size = f.name, f.size if f.transfer_method.value == "local_file" and f.upload_file_id and (not name or not size): - meta = self.db.query(FileMetadata).filter( - FileMetadata.id == f.upload_file_id, - FileMetadata.status == "completed" - ).first() + meta = meta_map.get(str(f.upload_file_id)) if meta: name = name or meta.file_name size = size or meta.file_size @@ -521,13 +528,20 @@ class AppChatService: } if files: + local_ids = [f.upload_file_id for f in files + if f.transfer_method.value == "local_file" and f.upload_file_id + and (not f.name or not f.size)] + meta_map = {} + if local_ids: + rows = self.db.query(FileMetadata).filter( + FileMetadata.id.in_(local_ids), + FileMetadata.status == "completed" + ).all() + meta_map = {str(r.id): r for r in rows} for f in files: name, size = f.name, f.size if f.transfer_method.value == "local_file" and f.upload_file_id and (not name or not size): - meta = self.db.query(FileMetadata).filter( - FileMetadata.id == f.upload_file_id, - FileMetadata.status == "completed" - ).first() + meta = meta_map.get(str(f.upload_file_id)) if meta: name = name or meta.file_name size = size or meta.file_size diff --git a/api/app/services/app_dsl_service.py b/api/app/services/app_dsl_service.py index 612b93fe..16aa8a3a 100644 --- a/api/app/services/app_dsl_service.py +++ b/api/app/services/app_dsl_service.py @@ -279,7 +279,7 @@ class AppDslService: tenant_id: uuid.UUID, warnings: list, now: datetime.datetime, - ) -> tuple[type(App), list]: + ) -> tuple[App, list[str]]: """覆盖已有应用的配置,类型不一致时抛出异常""" app = self.db.query(App).filter( App.id == app_id, diff --git a/api/app/services/draft_run_service.py b/api/app/services/draft_run_service.py index 52c3d7f3..b47bd4cd 100644 --- a/api/app/services/draft_run_service.py +++ b/api/app/services/draft_run_service.py @@ -1300,13 +1300,20 @@ class AgentRunService: } if files: from app.models.file_metadata_model import FileMetadata + local_ids = [f.upload_file_id for f in files + if f.transfer_method.value == "local_file" and f.upload_file_id + and (not f.name or not f.size)] + meta_map = {} + if local_ids: + rows = self.db.query(FileMetadata).filter( + FileMetadata.id.in_(local_ids), + FileMetadata.status == "completed" + ).all() + meta_map = {str(r.id): r for r in rows} for f in files: name, size = f.name, f.size if f.transfer_method.value == "local_file" and f.upload_file_id and (not name or not size): - meta = self.db.query(FileMetadata).filter( - FileMetadata.id == f.upload_file_id, - FileMetadata.status == "completed" - ).first() + meta = meta_map.get(str(f.upload_file_id)) if meta: name = name or meta.file_name size = size or meta.file_size