减少切分状态写入的重复克隆
让状态写入接口借用状态并在阻塞任务中写入序列化字节 保留 schema 与大小校验,避免每批次复制完整状态树
This commit is contained in:
+17
-23
@@ -42,30 +42,19 @@ pub fn project_relative_path(root: &Path, path: &Path) -> Result<String, String>
|
||||
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("<unknown>"),
|
||||
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("<unknown>"),
|
||||
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("<unknown>"),
|
||||
fs::metadata(path)
|
||||
.map(|metadata| metadata.len())
|
||||
.unwrap_or(0),
|
||||
state.trees.len(),
|
||||
state.bound.len(),
|
||||
state.problematic_nodes.len()
|
||||
bytes.len()
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
+6
-6
@@ -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()
|
||||
|
||||
@@ -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!(
|
||||
|
||||
Reference in New Issue
Block a user