Skip to content

Stop NavDataLoaderViewModel polling once nav data is loaded#10

Merged
RISCfuture merged 1 commit into
mainfrom
fix/navdata-loader-polling-hang
Jun 23, 2026
Merged

Stop NavDataLoaderViewModel polling once nav data is loaded#10
RISCfuture merged 1 commit into
mainfrom
fix/navdata-loader-polling-hang

Conversation

@RISCfuture

Copy link
Copy Markdown
Contributor

Summary

Removes a perpetual background poll that contends with the main context for SwiftData's persistent store coordinator — the dominant contributor to the launch-time app hangs SF50-TOLD-26 / SF50-TOLD-20, which are still occurring on the current 3.5.6 build (19 App Hang Fully Blocked events on 3.5.6+47, durations 2.4s–42s).

Background

The reported hangs share one signature: a Swift concurrency job on the main executor blocked in -[NSManagedObjectContext performBlockAndWait:], waiting for persistent-store-coordinator ownership. The launch path was already moved off the main context in prior releases, but NavDataLoaderViewModel.statePollingTask kept a while/sleep(0.5) loop running for the entire app session (the view model is held for the lifetime of ContentView), doing two fetches per tick on a background ModelContext. Every context on the shared ModelContainer serializes on a single coordinator, so this twice-a-second poll repeatedly contended with the main thread's faults.

Change

  • Resolve the loader state once at launch, then keep polling only while the loader is still needed (showLoader == true: no data yet, or a download in progress).
  • Once data is present and current, the loader is dismissed and the poll exits — so a returning user does zero background SwiftData work after launch.
  • The existing schema-version observer still revives state when a reload becomes necessary, and load() completion still drives dismissal.

Testing

  • swift format lint --strict and swiftlint --strict clean.
  • Built the SF50 TOLD scheme for the iOS 26.5 iPhone 16 simulator — succeeds.
  • Simulator, data-present path (UI-TESTING seed): launches straight to the Takeoff screen, loader dismissed — poll self-terminates, app fully functional.
  • Simulator, first-run path (fresh install, no data): the "Download Navigation Data" consent screen appears correctly, confirming the poll keeps running whenever the loader is needed (so post-download dismissal still fires).

The hang reduction itself is a production/contention effect not reproducible on the simulator; this PR is verified by code review plus regression checks of both loader paths.

🤖 Generated with Claude Code

`statePollingTask` ran a 0.5s `while`/`sleep` loop for the entire app
session, fetching the airport and NASR-cycle state twice a second on a
background `ModelContext`. Because every context on the shared
`ModelContainer` serializes on one persistent store coordinator, that
perpetual poll contended with the main context's SwiftData faults —
the dominant contributor to the launch-time `performBlockAndWait`
main-thread hangs (SF50-TOLD-26/-20), which remain active on 3.5.6.

Resolve the loader state once at launch and keep polling only while the
loader is still needed (no data yet, or a download in progress). Once
data is present and current the loader is dismissed and the poll stops,
so a returning user — the common case — does zero background SwiftData
work after launch. The existing schema-version observer continues to
revive state when a reload becomes necessary.

Refs SF50-TOLD-26, SF50-TOLD-20.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@RISCfuture RISCfuture merged commit f130aa5 into main Jun 23, 2026
8 of 9 checks passed
@RISCfuture RISCfuture deleted the fix/navdata-loader-polling-hang branch June 23, 2026 16:56
RISCfuture added a commit that referenced this pull request Jun 30, 2026
Reduce the main-actor SwiftData contention behind the launch-time
performBlockAndWait hangs (SF50-TOLD-26/-20), and quiet transient Sentry
noise:

- Stop NavDataLoaderViewModel's perpetual 0.5s state poll once nav data is
  loaded, so a returning user does zero background SwiftData work after
  launch (#10).
- Observe runway NOTAM changes with withObservationTracking instead of a
  500ms main-actor poll for the lifetime of the takeoff/landing screen
  (#11).
- Treat TLS handshake failures (secureConnectionFailed) as transient and
  stop double-reporting weather-fetch network errors to Sentry (#9).

Refs SF50-TOLD-26, SF50-TOLD-20, SF50-TOLD-2D, SF50-TOLD-21.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.

1 participant