fix(official-sync): 发布成功后立即提交版本状态事务

publish() 切换 current symlink 后,写最终 snapshot 或 complete_version_state
若失败会经 ? 提前返回,此时 VersionStateGuard 尚未 commit,其 Drop 会把这个
磁盘上已发布(current 已指向)的版本记入 failed_versions,造成状态与磁盘不一致。

改为在 publish() 成功后立即取出完成记录并 commit 版本状态事务,随后 snapshot
与 version-state 写入失败降级为可下轮重试的警告(不再 ? 中断、不再误记 failed);
snapshot_written 也改为仅在实际写入成功时置 Some。

对应 issue #18 维护清单 1-3。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-16 07:17:51 -07:00
co-authored by Claude Fable 5
parent 4c123b9560
commit 4d818f512c
+27 -7
View File
@@ -1389,10 +1389,27 @@ impl OfficialUpdateService {
let published_version_path = publish_layout
.publish(&publish_plan)
.map_err(anyhow::Error::msg)?;
// current symlink 已切换,资源发布成功。先取出完成版本记录并立即结束版本状态
// 事务,使后续 snapshot / version-state 写入失败不会把这个已发布版本经
// VersionStateGuard::Drop 误记为 failed,而是降级为可下轮重试的警告。
let completed_record = version_state_guard.record()?.clone();
version_state_guard.commit();
let final_snapshot_path = snapshot_path_for(config, &published_version_path);
if config.snapshot_path.is_some() {
write_snapshot(&final_snapshot_path, &current_update_snapshot)?;
let snapshot_written = if config.snapshot_path.is_some() {
match write_snapshot(&final_snapshot_path, &current_update_snapshot) {
Ok(()) => true,
Err(error) => {
progress(OfficialUpdateProgress::new(
"publish",
format!("资源已发布,但写入最终 snapshot 失败(下轮可重试):{error}"),
));
false
}
}
} else {
false
};
report.update_status = OfficialUpdateStatus::Downloaded;
report.active_resource_root = published_version_path.clone();
@@ -1409,15 +1426,18 @@ impl OfficialUpdateService {
report.local_manifest_verified_count = final_audit.verified_count();
report.local_manifest_repair_needed_count = final_audit.repair_needed_count();
report.verification_summary = final_verification_summary;
report.snapshot_written = Some(final_snapshot_path.clone());
let completed_record = version_state_guard.record()?.clone();
complete_version_state(
report.snapshot_written = snapshot_written.then(|| final_snapshot_path.clone());
if let Err(error) = complete_version_state(
&version_state_path,
completed_record,
&published_version_path,
&final_snapshot_path,
)?;
version_state_guard.commit();
) {
progress(OfficialUpdateProgress::new(
"publish",
format!("资源已发布,但写入版本状态失败(下轮可重试):{error}"),
));
}
progress(OfficialUpdateProgress::new(
"finish",