fix(menubar): run prefetchAll in a detached task so the refresh loop starts immediately

prefetchAll was awaited inside the refresh loop after the first cycle.
On large corpora the All Time parse takes 60+ seconds and kept the Today
refresh blocked for that whole window, so the status label got stuck for
minutes at a time while the CLI was returning fresh numbers.

Detach prefetchAll into its own @MainActor task. The popover still gets
the benefit of pre-warmed period caches, the refresh loop ticks every 15
seconds regardless.
This commit is contained in:
iamtoruk 2026-04-21 05:22:34 -07:00
parent f2a2b53ae7
commit 2467578a52

View file

@ -72,12 +72,11 @@ final class AppDelegate: NSObject, NSApplicationDelegate, NSPopoverDelegate {
private func startRefreshLoop() {
refreshTask = Task { [weak self] in
guard let s = self else { return }
// First cycle: fetch current view, then prefetch all periods in background
// First cycle: fetch today so the status icon has a number within seconds of launch.
await s.store.refreshQuietly(period: .today)
s.refreshStatusButton()
await s.store.refresh(includeOptimize: true)
s.refreshStatusButton()
await s.store.prefetchAll()
while !Task.isCancelled {
try? await Task.sleep(nanoseconds: refreshIntervalNanos)
@ -88,6 +87,15 @@ final class AppDelegate: NSObject, NSApplicationDelegate, NSPopoverDelegate {
s.refreshStatusButton()
}
}
// Prefetch the remaining periods in a detached task. This used to be awaited inside the
// refresh loop, but on large corpora the All Time / Month period can take 60+ seconds to
// parse and blocked Today's refresh for that whole window, so the status label drifted
// out of sync with the CLI until prefetchAll finally returned.
Task { @MainActor [weak self] in
guard let s = self else { return }
await s.store.prefetchAll()
}
}
private func observeStore() {