diff --git a/apps/ai-game-creator-shell/src-tauri/src/export/registry.rs b/apps/ai-game-creator-shell/src-tauri/src/export/registry.rs index cbf66fa52..275146002 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/export/registry.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/export/registry.rs @@ -172,9 +172,16 @@ fn temp_path(path: &Path) -> PathBuf { .unwrap_or_else(|| "registry.json".to_string()); // 临时文件名必须**每次写都不同**:只用 pid 的话,同一进程里两个并发写共用同一个临时文件, // 一个会截断另一个正在写的内容,rename 也会互相抢。进程内原子计数器保证不重名。 + // + // 计数器从 0 重来,所以还要带上「现在」:上一次进程崩在 `create_new` 与 rename 之间时, + // 会留下 `.tmp` 残骸;系统把同一个 pid 再分给新进程时,只靠 pid + 序号会撞上那份残骸, + // 而 `create_new` 会直接以 already-exists 失败。纳秒时间戳让重启后的第一次写也不再撞名。 let sequence = TEMP_FILE_SEQUENCE.fetch_add(1, Ordering::Relaxed); + let stamp = std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .map_or(0, |elapsed| elapsed.as_nanos()); path.with_file_name(format!( - ".{file_name}.{}.{sequence}.tmp", + ".{file_name}.{}.{sequence}.{stamp}.tmp", std::process::id() )) }