Skip to content

fix: reset OTA retry gate on cold restart#12564

Open
huhuanming wants to merge 2 commits into
release/v6.5.0from
codex/fix-ios-ota-recovery-v2
Open

fix: reset OTA retry gate on cold restart#12564
huhuanming wants to merge 2 commits into
release/v6.5.0from
codex/fix-ios-ota-recovery-v2

Conversation

@huhuanming

@huhuanming huhuanming commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Move the OTA download-attempt gate from persisted MMKV state to the ServiceAppUpdate background-service instance.
  • A cold background-service/process restart now starts with a fresh budget, so an exhausted value from an earlier launch cannot permanently block OTA recovery.
  • Keep the active-process bound: eight real download attempts are allowed; the next entry check blocks attempt nine.
  • Reset the in-memory budget when update cache is cleared. Reset also deletes the legacy MMKV key for cleanup, but the gate never reads or writes that value.

Scope

The fix is intentionally limited to one production TypeScript file and one existing test file.

  • No native source or patch-package changes.
  • No front-end recovery state-machine changes.
  • No dependency or build-configuration changes.
  • The shared background-service path gives iOS, Android, and Desktop the same gate lifecycle.

Preserved safeguards

  • Per-invocation bounded retry and network-aware backoff.
  • Download mutex.
  • One-shot 401/403 signed-URL refresh.
  • SHA256/signature and unrecoverable-error checks.
  • Existing native range/resume behavior.

Validation

  • 3 targeted Jest suites passed (394 tests).
  • Post-rebase core service/retry suites passed again (239 tests).
  • Full repository TypeScript check passed.
  • Type-aware oxlint passed with 0 warnings and 0 errors on both changed files.
  • Prettier and diff whitespace checks passed.

Runtime ownership

The counter lives only in the bg JS ServiceAppUpdate instance. Main calls it through backgroundApiProxy; native download resources remain unchanged. A new bg service instance has no counter, and “Clear update cache” explicitly clears the current instance’s counter.

@huhuanming
huhuanming force-pushed the codex/fix-ios-ota-recovery-v2 branch from 52d0421 to afcf07e Compare July 21, 2026 05:21
@huhuanming
huhuanming force-pushed the codex/fix-ios-ota-recovery-v2 branch from afcf07e to 0ba3bc5 Compare July 21, 2026 13:06
@huhuanming huhuanming changed the title fix: recover OTA downloads after retry exhaustion fix: reset OTA retry gate on cold restart Jul 21, 2026
@huhuanming
huhuanming marked this pull request as ready for review July 21, 2026 13:38
@huhuanming
huhuanming enabled auto-merge (squash) July 21, 2026 13:41
return appStorage.syncStorage.getObject<IDownloadAttemptBudgetRecord>(
this.downloadAttemptBudgetStorageKey,
);
return this.downloadAttemptBudget;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

当同一 OTA 目标持续下载失败并触发冷启动或 bg JS runtime 重建时,这里只从 ServiceAppUpdate 实例字段读取预算,原先 MMKV 中跨重启累计的次数会被完全忽略。ServiceAppUpdate 属于 bg runtime,因此重建会丢失这份 JS heap 状态,而原生 .resume/.partial 下载资源仍会保留;结果是同一永久失败目标每次重启都重新获得完整尝试预算,跨重启的 DownloadGaveUpError 终止保证失效,并可能反复消耗流量和启动时间。

请继续通过 syncStorage 持久化预算,并将记录绑定到稳定的 installed native runtime identity;仅在该 identity 确认变化时重置旧预算,这样既能恢复 iOS OTA,又能保留同一失败目标的跨重启收敛。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants