mirror of
https://github.com/tiennm99/ccs.git
synced 2026-07-15 20:20:09 +00:00
fix(bar-app): periodic background refresh so the glance self-heals
The menu only re-polled on open or after a mutation, so if the server briefly dropped rows (e.g. a backend restart mid-session) the dropdown could stay stuck showing stale/missing rows until reopened. Add a 60s background poll that reconnects if the client was lost and reloads non-force (respecting server-side caches, so it never hammers providers). As a bonus, alerts now evaluate every interval instead of only on menu-open, making them genuinely proactive.
This commit is contained in:
@@ -37,6 +37,12 @@ final class BarViewModel: ObservableObject {
|
||||
private let home: String
|
||||
private var client: CCSBarClient?
|
||||
private var debouncer = RefreshDebouncer(interval: 15)
|
||||
/// Periodic background refresh so the glance self-heals from a transient
|
||||
/// server gap (e.g. a momentary backend restart that dropped the native rows)
|
||||
/// without the user having to reopen the menu. Cheap + safe: it reads the
|
||||
/// local server's caches and never hammers providers (native quota is
|
||||
/// TTL-gated server-side).
|
||||
private var pollTask: Task<Void, Never>?
|
||||
private let prefs: BarPreferences
|
||||
private let notifier: NotificationDelivering
|
||||
|
||||
@@ -58,6 +64,23 @@ final class BarViewModel: ObservableObject {
|
||||
self.glanceMode = prefs.load().glanceMode
|
||||
self.spendChartStyle = SpendChartStyleStore.load()
|
||||
reconnect()
|
||||
startBackgroundPolling()
|
||||
}
|
||||
|
||||
/// Periodically re-poll for the app's lifetime so a transient empty/missing-row
|
||||
/// state recovers on its own within one interval — each tick reconnects if the
|
||||
/// client/discovery was lost, then loads (non-force, so it respects the
|
||||
/// server-side caches). This is what prevents the menu from getting stuck after
|
||||
/// the server momentarily restarts.
|
||||
private func startBackgroundPolling() {
|
||||
pollTask?.cancel()
|
||||
pollTask = Task { [weak self] in
|
||||
while !Task.isCancelled {
|
||||
try? await Task.sleep(for: .seconds(60))
|
||||
guard let self else { return }
|
||||
await self.load(force: false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Re-read prefs after the preferences sheet writes through, so the next poll
|
||||
|
||||
Reference in New Issue
Block a user