迁移 UI 编辑器素材导入到阻塞工作线程

将本地与远端素材导入的同步校验和文件事务移入 Tokio blocking worker
保持项目写锁只覆盖 worker 内的连续同步临界区
补充异步导入命令的本地图片导入回归测试
This commit is contained in:
2026-08-19 13:06:50 +08:00
parent 5528fdf64a
commit f1ebd47ff7
@@ -44,7 +44,7 @@ pub(crate) enum UiEditorAssetImportRequest {
#[cfg(test)]
mod ui_editor_asset_import_request_tests {
use super::UiEditorAssetImportRequest;
use super::*;
#[test]
fn local_request_accepts_tauri_camel_case_fields() {
@@ -63,6 +63,42 @@ mod ui_editor_asset_import_request_tests {
assert!(matches!(request, UiEditorAssetImportRequest::Local { .. }));
}
#[tokio::test]
async fn asset_import_async_command_completes_local_file_import() {
let project = tempfile::tempdir().expect("create project directory");
let root = project.path();
init_local_game_project_at(root, "ui-editor-import", "UI 编辑器导入测试")
.expect("initialize project");
let source = tempfile::NamedTempFile::new().expect("create image source");
fs::write(
source.path(),
[
0x89, b'P', b'N', b'G', b'\r', b'\n', 0x1a, b'\n', 0, 0, 0, 0,
],
)
.expect("write image source");
let result = import_ui_editor_assets(UiEditorAssetImportRequest::Local {
project_path: root.to_string_lossy().into_owned(),
local_source_paths: vec![source.path().to_string_lossy().into_owned()],
local_policy: AssetImportPolicy {
destination: "assets/uploads".to_string(),
accepted_media_types: vec!["image/png".to_string()],
accepted_extensions: vec!["png".to_string()],
},
local_requirements: AssetImportRequirements {
max_items: 1,
max_file_size_bytes: Some(1024),
max_total_size_bytes: Some(1024),
},
})
.await
.expect("import local image through blocking worker");
assert_eq!(result.assets.len(), 1);
assert!(root.join(&result.assets[0].local_path).is_file());
}
}
fn validate_asset_import_policy(policy: &AssetImportPolicy) -> Result<bool, String> {
@@ -175,6 +211,14 @@ fn validate_remote_asset_import_requirements(
#[tauri::command]
pub(crate) async fn import_ui_editor_assets(
request: UiEditorAssetImportRequest,
) -> Result<LocalImportResult, String> {
tokio::task::spawn_blocking(move || import_ui_editor_assets_blocking(request))
.await
.map_err(|error| format!("UI 编辑器素材导入任务意外终止:{error}"))?
}
fn import_ui_editor_assets_blocking(
request: UiEditorAssetImportRequest,
) -> Result<LocalImportResult, String> {
match request {
UiEditorAssetImportRequest::Local {
@@ -211,7 +255,6 @@ pub(crate) async fn import_ui_editor_assets(
remote_assets,
remote_requirements.max_file_size_bytes.unwrap_or(u64::MAX),
)
.await
}
}
}
@@ -2161,7 +2204,7 @@ mod ui_editor_font_tests {
}
}
pub(crate) async fn import_ui_editor_remote_assets(
pub(crate) fn import_ui_editor_remote_assets(
project_path: String,
assets: Vec<serde_json::Value>,
max_file_size: u64,