Skip to content

Move NavDataLoader polling to background context (fixes app hang)#3

Merged
RISCfuture merged 2 commits intomainfrom
worktree-agent-a7911074
Apr 12, 2026
Merged

Move NavDataLoader polling to background context (fixes app hang)#3
RISCfuture merged 2 commits intomainfrom
worktree-agent-a7911074

Conversation

@RISCfuture
Copy link
Copy Markdown
Contributor

Summary

  • Fixes SF50-TOLD-20 (15-16s app hang, 13 events / 13 users)
  • Contributes to SF50-TOLD-1X and SF50-TOLD-22 (DB on main thread)
  • The 500ms polling loop in `setupObservation()` was reading `container.mainContext` while `NavDataLoader` held the persistent store coordinator lock during batch writes — causing 15-16s main-thread hangs
  • Extracts a `nonisolated fetchLoaderState(context:)` helper that combines Airport existence + NASR expiration fetches into a value-type tuple
  • Polling loop now runs in `Task.detached` with its own `ModelContext(container)`, reading via MVCC without blocking the main thread
  • `applyState` skips redundant assignments to avoid unnecessary `@Observable` notifications

Test plan

  • Unit tests (SF50 Shared Unit Tests) pass
  • UI tests (47 tests, SF50 TOLD UI Tests) pass
  • swift format + swiftlint clean

🤖 Generated with Claude Code

RISCfuture and others added 2 commits April 11, 2026 17:20
Fixes SF50-TOLD-20 (15-16s app hang) and contributes to SF50-TOLD-1X
and SF50-TOLD-22 (DB on main thread).

The polling loop in setupObservation() ran setAnyAirports every 500ms
on container.mainContext, calling fetchNASRExpiration which also
queried mainContext. During NavDataLoader batch writes, the main
context's fetch blocked waiting for the persistent store coordinator
lock, causing 15-16s main-thread hangs.

This extracts a nonisolated fetchLoaderState(context:) helper that
combines the Airport existence check and NASR expiration fetch into
a value-type tuple. The polling loop now runs in Task.detached with
its own ModelContext(container), reading via MVCC without blocking
the main thread. Results are applied back on MainActor, skipping
redundant property assignments to avoid unnecessary @observable
notifications.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Moves the four nonisolated helper methods out of NavDataLoaderViewModel
into a private file-scope enum. File-scope types are nonisolated by
default, so the helpers become callable from both MainActor and
background contexts without annotations.

Also introduces a named NavDataStateHelper.State struct in place of
the previous (noData, needsLoad, canSkip) tuple for self-documenting
call sites.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@RISCfuture RISCfuture merged commit 4ddd497 into main Apr 12, 2026
4 checks passed
@RISCfuture RISCfuture deleted the worktree-agent-a7911074 branch April 12, 2026 20:44
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