Skip to content

Route remote command polling through TaskScheduler#592

Merged
bjorkert merged 1 commit intofeature/remote-command-pollingfrom
feature/remote-command-polling-scheduler
Apr 10, 2026
Merged

Route remote command polling through TaskScheduler#592
bjorkert merged 1 commit intofeature/remote-command-pollingfrom
feature/remote-command-polling-scheduler

Conversation

@bjorkert
Copy link
Copy Markdown
Contributor

@bjorkert bjorkert commented Apr 9, 2026

Summary

  • Replaces the parallel Timer.scheduledTimer used for post-remote-command polling with a new .remoteCommandPoll TaskScheduler task, so the aggressive polling runs through the same scheduler as every other recurring fetch in the app.
  • The tick reschedules .deviceStatus and .treatments to fire immediately and reschedules itself for the next 3s interval. The task is parked at .distantFuture when the window closes (timeout or fresh data detected) — the same transient resting state every task already passes through between fire and reschedule.
  • Drops .fetchBG from the polled set: no remote command produces a BG entry, and RemoteCommandDataSignature doesn't inspect bgData, so the fetch was dead weight during the window.

Why

  • Avoids having two independent timing mechanisms running during the 30s window. Previously the parallel Timer called bgTaskAction/deviceStatusAction/treatmentsTaskAction directly every 3s, each of which internally rescheduleTask'd itself back to its normal cadence — a continuous double-reschedule war.
  • Uniform app backgrounding behavior: if the app backgrounds mid-window, TaskScheduler's lifecycle applies; no separate Timer lifecycle to reason about.
  • No deinit timer invalidation needed — TaskScheduler owns the lifetime.

Safety notes

  • .remoteCommandPoll is lazily registered only when startRemoteCommandPolling is called from the .remoteCommandSucceeded notification. scheduleAllTasks() is not touched, so no app refresh/reset path will accidentally spawn it.
  • TaskID.allCases is only iterated in fireOverdueTasks, which filters on nextRun <= now. A parked .distantFuture entry is skipped forever until an explicit rescheduleTask revives it.
  • MainViewController is the app root VC, but the scheduleTask closure uses [weak self] as a belt-and-suspenders guard against any future refactor that deinits it.

Replace the parallel Timer with a .remoteCommandPoll TaskScheduler task
so the aggressive post-remote-command polling runs through the same
scheduler as every other recurring fetch. The tick reschedules
.deviceStatus and .treatments to fire immediately, then reschedules
itself for the next interval. Parked at .distantFuture when the window
closes (timeout or fresh data detected).

Drop .fetchBG from the polled set: no remote command produces a BG
entry, and the completion signature doesn't look at bgData, so the
fetch was dead weight during the window.
@bjorkert bjorkert requested a review from codebymini April 9, 2026 14:04
@bjorkert bjorkert merged commit b3c73a9 into feature/remote-command-polling Apr 10, 2026
@bjorkert bjorkert deleted the feature/remote-command-polling-scheduler branch April 10, 2026 08:31
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