feat: harden official sync scheduling and integrity

This commit is contained in:
2026-07-11 01:06:02 +08:00
parent 2bdc55a1be
commit 264e78c440
11 changed files with 474 additions and 99 deletions
+47 -49
View File
@@ -627,35 +627,39 @@ impl OfficialUpdateService {
sync_plan.decision, config.force, remote_should_download
),
));
let pull_plan = if config.audit_local || remote_should_download || config.plan {
progress(OfficialUpdateProgress::new(
"plan",
"building official pull plan from seed catalogs",
));
Some(build_pull_plan(
&server_info,
&connection_group,
&app_version,
platforms,
&fetcher,
&mut progress,
&mut should_cancel,
)?)
} else {
progress(OfficialUpdateProgress::new(
"plan",
"pull plan not needed for clean remote state and disabled plan output",
));
None
};
if let Some(pull_plan) = pull_plan.as_ref() {
let url_count = pull_plan.all_urls().map_err(anyhow::Error::msg)?.len();
progress(OfficialUpdateProgress::new(
"plan",
format!("pull plan contains {url_count} official URLs"),
));
}
let local_audit = if config.audit_local {
progress(OfficialUpdateProgress::new(
"plan",
"building official pull plan from latest seed catalogs",
));
let pull_plan = build_pull_plan(
&server_info,
&connection_group,
&app_version,
platforms,
&fetcher,
&mut progress,
&mut should_cancel,
)?;
let url_count = pull_plan.all_urls().map_err(anyhow::Error::msg)?.len();
progress(OfficialUpdateProgress::new(
"plan",
format!("pull plan contains {url_count} official URLs"),
));
let local_state = fetcher
.local_resource_state(&pull_plan)
.map_err(anyhow::Error::msg)?;
let has_local_resources = local_state.has_any_resources();
progress(OfficialUpdateProgress::new(
"local-state",
format!(
"manifest_entries={} existing_files={} has_local_resources={}",
local_state.manifest_entry_count,
local_state.existing_file_count,
has_local_resources
),
));
let should_audit_local = config.audit_local && has_local_resources;
let local_audit = if should_audit_local {
progress(OfficialUpdateProgress::new(
"audit",
format!(
@@ -665,13 +669,15 @@ impl OfficialUpdateService {
));
Some(
fetcher
.audit_local_manifest(
pull_plan
.as_ref()
.ok_or_else(|| anyhow::anyhow!("local audit requires a pull plan"))?,
)
.audit_local_manifest(&pull_plan)
.map_err(anyhow::Error::msg)?,
)
} else if config.audit_local {
progress(OfficialUpdateProgress::new(
"audit",
"no local resources found; skipping local audit before first full pull",
));
None
} else {
progress(OfficialUpdateProgress::new(
"audit",
@@ -692,7 +698,8 @@ impl OfficialUpdateService {
.as_ref()
.map(|audit| !audit.is_clean())
.unwrap_or(false);
let should_download = remote_should_download || repair_needed;
let initial_pull_needed = !has_local_resources;
let should_download = remote_should_download || repair_needed || initial_pull_needed;
progress(OfficialUpdateProgress::new(
"audit",
format!(
@@ -703,8 +710,8 @@ impl OfficialUpdateService {
progress(OfficialUpdateProgress::new(
"decision",
format!(
"final should_download={} repair_needed={}",
should_download, repair_needed
"final should_download={} repair_needed={} initial_pull_needed={}",
should_download, repair_needed, initial_pull_needed
),
));
check_shutdown_requested(&mut should_cancel)?;
@@ -760,13 +767,7 @@ impl OfficialUpdateService {
if config.dry_run {
if config.plan {
let urls = pull_plan
.as_ref()
.ok_or_else(|| {
anyhow::anyhow!("dry-run plan requested but no pull plan exists")
})?
.all_urls()
.map_err(anyhow::Error::msg)?;
let urls = pull_plan.all_urls().map_err(anyhow::Error::msg)?;
report.download_url_count = Some(urls.len());
report.download_urls = urls;
progress(OfficialUpdateProgress::new(
@@ -791,9 +792,6 @@ impl OfficialUpdateService {
}
check_shutdown_requested(&mut should_cancel)?;
let pull_plan = pull_plan
.as_ref()
.ok_or_else(|| anyhow::anyhow!("download requested but no pull plan exists"))?;
let download_url_count = pull_plan.all_urls().map_err(anyhow::Error::msg)?.len();
progress(OfficialUpdateProgress::new(
"download",
@@ -801,7 +799,7 @@ impl OfficialUpdateService {
));
let pull_report = fetcher
.pull_with_progress_and_cancellation(
pull_plan,
&pull_plan,
|event| {
progress(progress_from_pull_event(event));
},
@@ -824,7 +822,7 @@ impl OfficialUpdateService {
));
check_shutdown_requested(&mut should_cancel)?;
let final_audit = fetcher
.audit_local_manifest(pull_plan)
.audit_local_manifest(&pull_plan)
.map_err(anyhow::Error::msg)?;
progress(OfficialUpdateProgress::new(
"snapshot",