From d8a4e3523257d4a7660f9f5454ff52fb1eb8ef5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=BE=B7=E5=AE=87?= Date: Sat, 12 Sep 2026 13:16:25 +0800 Subject: [PATCH] =?UTF-8?q?=E5=87=8F=E5=B0=91=E5=88=87=E5=88=86=E7=8A=B6?= =?UTF-8?q?=E6=80=81=E5=86=99=E5=85=A5=E7=9A=84=E9=87=8D=E5=A4=8D=E5=85=8B?= =?UTF-8?q?=E9=9A=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 让状态写入接口借用状态并在阻塞任务中写入序列化字节 保留 schema 与大小校验,避免每批次复制完整状态树 --- .../commands/separation/persistence.rs | 40 ++++++++----------- .../commands/separation/workflow/mod.rs | 12 +++--- .../src-tauri/src/ui_editor/commands/utils.rs | 6 +-- 3 files changed, 25 insertions(+), 33 deletions(-) diff --git a/apps/ai-game-creator-shell/src-tauri/src/ui_editor/commands/separation/persistence.rs b/apps/ai-game-creator-shell/src-tauri/src/ui_editor/commands/separation/persistence.rs index 00221e9a8..c35737d86 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/ui_editor/commands/separation/persistence.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/ui_editor/commands/separation/persistence.rs @@ -42,30 +42,19 @@ pub fn project_relative_path(root: &Path, path: &Path) -> Result Ok(value) } -pub async fn write_separation_state(path: PathBuf, state: SeparationState) -> Result<(), String> { +pub async fn write_separation_state(path: PathBuf, state: &SeparationState) -> Result<(), String> { + if state.schema_version != SEPARATION_STATE_SCHEMA_VERSION { + app_log!("ui_separation.error stage=state_write reason=schema_mismatch"); + return Err("不支持的 separation state schema".to_string()); + } + let state = serde_json::to_vec_pretty(state) + .map_err(|error| format!("序列化 separation state 失败:{error}"))?; tokio::task::spawn_blocking(move || write_separation_state_blocking(&path, &state)) .await .map_err(|error| format!("写入 separation state 任务失败:{error}"))? } -fn write_separation_state_blocking(path: &Path, state: &SeparationState) -> Result<(), String> { - if state.schema_version != SEPARATION_STATE_SCHEMA_VERSION { - app_log!("ui_separation.error stage=state_write reason=schema_mismatch"); - return Err("不支持的 separation state schema".to_string()); - } - app_log!( - "ui_separation.state_write.start file={} trees={} bound={} problematic={}", - path.file_name() - .and_then(|name| name.to_str()) - .unwrap_or(""), - state.trees.len(), - state.bound.len(), - state.problematic_nodes.len() - ); - let bytes = serde_json::to_vec_pretty(state).map_err(|error| { - app_log!("ui_separation.error stage=state_write reason=serialize error={error}"); - format!("序列化 separation state 失败:{error}") - })?; +fn write_separation_state_blocking(path: &Path, bytes: &[u8]) -> Result<(), String> { if bytes.len() > SEPARATION_STATE_MAX_BYTES { app_log!( "ui_separation.error stage=state_write reason=too_large bytes={} max_bytes={}", @@ -77,6 +66,13 @@ fn write_separation_state_blocking(path: &Path, state: &SeparationState) -> Resu SEPARATION_STATE_MAX_BYTES )); } + app_log!( + "ui_separation.state_write.start file={} bytes={}", + path.file_name() + .and_then(|name| name.to_str()) + .unwrap_or(""), + bytes.len() + ); let parent = path.parent().ok_or_else(|| { app_log!("ui_separation.error stage=state_write reason=missing_parent"); "separation state 路径缺少父目录".to_string() @@ -95,16 +91,14 @@ fn write_separation_state_blocking(path: &Path, state: &SeparationState) -> Resu format!("安装 separation state 失败:{error}") })?; app_log!( - "ui_separation.state_write.completed file={} bytes={} trees={} bound={} problematic={}", + "ui_separation.state_write.completed file={} bytes={}", path.file_name() .and_then(|name| name.to_str()) .unwrap_or(""), fs::metadata(path) .map(|metadata| metadata.len()) .unwrap_or(0), - state.trees.len(), - state.bound.len(), - state.problematic_nodes.len() + bytes.len() ); Ok(()) } diff --git a/apps/ai-game-creator-shell/src-tauri/src/ui_editor/commands/separation/workflow/mod.rs b/apps/ai-game-creator-shell/src-tauri/src/ui_editor/commands/separation/workflow/mod.rs index 7a24146fc..960cc7ee9 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/ui_editor/commands/separation/workflow/mod.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/ui_editor/commands/separation/workflow/mod.rs @@ -106,7 +106,7 @@ pub(crate) async fn separate_ui_impl( image.pixel_size.x.round() as u32, image.pixel_size.y.round() as u32 ); - write_separation_state(state_path.clone(), separation.clone()) + write_separation_state(state_path.clone(), &separation) .await .map_err(|error| { app_log!( @@ -156,7 +156,7 @@ pub(crate) async fn separate_ui_impl( Ok(value) => value, Err(error) => { app_log!("ui_separation.error stage=image_edit tree_index={} batch_index={} error={error}", tree_index, batch_index); - write_separation_state(state_path.clone(), separation.clone()).await?; + write_separation_state(state_path.clone(), &separation).await?; return Err(error); } }; @@ -170,7 +170,7 @@ pub(crate) async fn separate_ui_impl( Ok(dimensions) => dimensions, Err(error) => { app_log!("ui_separation.error stage=processed_image_write tree_index={} batch_index={} error={error}", tree_index, batch_index); - write_separation_state(state_path.clone(), separation.clone()).await?; + write_separation_state(state_path.clone(), &separation).await?; return Err(error); } }; @@ -186,7 +186,7 @@ pub(crate) async fn separate_ui_impl( Ok(value) => value, Err(error) => { app_log!("ui_separation.error stage=visual_binding tree_index={} batch_index={} error={error}", tree_index, batch_index); - write_separation_state(state_path.clone(), separation.clone()).await?; + write_separation_state(state_path.clone(), &separation).await?; return Err(error); } }; @@ -237,7 +237,7 @@ pub(crate) async fn separate_ui_impl( } if let Some(error) = cut_error { app_log!("ui_separation.error stage=cut_batch tree_index={} batch_index={} error={error}", tree_index, batch_index); - write_separation_state(state_path.clone(), separation.clone()).await?; + write_separation_state(state_path.clone(), &separation).await?; return Err(error); } patch::apply_batch_patch( @@ -247,7 +247,7 @@ pub(crate) async fn separate_ui_impl( &cut_paths, processed_dimensions, )?; - write_separation_state(state_path.clone(), separation.clone()).await?; + write_separation_state(state_path.clone(), &separation).await?; app_log!( "ui_separation.batch_completed tree_index={} batch_index={} cuts={} bound={} problematic={} elapsed_ms={}", tree_index, batch_index, cut_paths.len(), separation.bound.len(), separation.problematic_nodes.len(), batch_started.elapsed().as_millis() diff --git a/apps/ai-game-creator-shell/src-tauri/src/ui_editor/commands/utils.rs b/apps/ai-game-creator-shell/src-tauri/src/ui_editor/commands/utils.rs index d432c09e1..c9b5e2bc9 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/ui_editor/commands/utils.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/ui_editor/commands/utils.rs @@ -70,10 +70,8 @@ where max_retries, error ); - tokio::time::sleep(std::time::Duration::from_millis( - 200 * (attempt as u64 + 1), - )) - .await; + tokio::time::sleep(std::time::Duration::from_millis(200 * (attempt as u64 + 1))) + .await; let serialized = serde_json::to_string(&value) .map_err(|serialize_error| format!("序列化修复反馈失败:{serialize_error}"))?; history.push(LlmMessage::system(format!(