From 63b7ef366563bd985a9668fc36e4ea1391b9bcd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=BE=B7=E5=AE=87?= Date: Tue, 6 Oct 2026 19:23:36 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B0=8F=E7=BA=A2=E4=B9=A6=E5=AF=BC=E5=87=BA?= =?UTF-8?q?=E4=B8=89=E6=9D=A1=E8=AF=BB=E5=86=99=E5=91=BD=E4=BB=A4=E6=8C=AA?= =?UTF-8?q?=E5=88=B0=E9=98=BB=E5=A1=9E=E7=BA=BF=E7=A8=8B=E6=B1=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - commands 新增 offload:用 tokio::task::spawn_blocking 包住同步文件 IO - read / readHash / save 三条命令改走 offload,JoinError 收口成 ExportUnavailable --- .../src/export/draft/xhs_minitool/commands.rs | 39 +++++++++++++++++-- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/apps/ai-game-creator-shell/src-tauri/src/export/draft/xhs_minitool/commands.rs b/apps/ai-game-creator-shell/src-tauri/src/export/draft/xhs_minitool/commands.rs index 9e17d5972..425a44d40 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/export/draft/xhs_minitool/commands.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/export/draft/xhs_minitool/commands.rs @@ -31,7 +31,11 @@ use super::{build, script}; pub(crate) async fn read_xhs_minitool_export( project_path: String, ) -> Result { - let result = read_content(&project_path); + let result = offload({ + let project_path = project_path.clone(); + move || read_content(&project_path) + }) + .await; report("read", &project_path, &result); result } @@ -43,7 +47,11 @@ pub(crate) async fn read_xhs_minitool_export( pub(crate) async fn read_xhs_minitool_export_hash( project_path: String, ) -> Result { - let result = read_content_hash(&project_path); + let result = offload({ + let project_path = project_path.clone(); + move || read_content_hash(&project_path) + }) + .await; report("readHash", &project_path, &result); result } @@ -58,7 +66,13 @@ pub(crate) async fn save_xhs_minitool_export_form( form: XHSMiniToolExportForm, base_hash: String, ) -> Result { - let result = save_form(&project_path, &form, &base_hash); + let result = offload({ + let project_path = project_path.clone(); + let form = form.clone(); + let base_hash = base_hash.clone(); + move || save_form(&project_path, &form, &base_hash) + }) + .await; report("save", &project_path, &result); if let Ok(hash) = &result { app_log!( @@ -109,6 +123,25 @@ fn project_root(project_path: &str) -> Result { Ok(root) } +/// 把小块同步 IO 挪到 Tokio 的阻塞线程池。 +/// +/// 读命令每 2 秒被轮询一次,注册表 + `package.json` 探测虽然小,但直接在 `async fn` 里做同步 +/// 文件 IO 会占着 worker 线程,拖慢同一 runtime 上的其它异步任务(构建子进程、SpacetimeDB +/// 客户端)。任务 panic 时 `JoinError` 收口成 `ExportUnavailable`,走各命令既有的失败表。 +async fn offload(job: F) -> Result +where + T: Send + 'static, + E: From + Send + 'static, + F: FnOnce() -> Result + Send + 'static, +{ + match tokio::task::spawn_blocking(job).await { + Ok(result) => result, + Err(error) => Err(E::from(ExportUnavailable::new(format!( + "后台执行导出读写任务失败:{error}" + )))), + } +} + fn read_content(project_path: &str) -> Result { let root = project_root(project_path)?; Ok(content(