Scheduler core with period keys and catch-up (Feature 20) #171

3 Commits
Author SHA1 Message Date
dev_agentandClaude Opus 5.5 bcd875c11f Retry a failed claim for its own period before later fire times
CI / ci (push) Successful in 7m29s
CI / ci (pull_request) Successful in 7m44s
A failed claim was retried by recomputing the most recent fire time from
the new now, so a daily claim that failed on 7 October and recovered after
the 8 October fire claimed only 8 October: the 7 October period was never
claimed nor recorded as missed. The scheduler now keeps each failed
claim's fire time and claims that same period every ClaimRetry until it
succeeds, applies the catch-up rule to it then, and only afterwards
handles later fire times and settings changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 19:02:09 -04:00
dev_agentandClaude Opus 5.5 6f7e1d2342 Apply settings changes at their save time and retry failed claims
CI / ci (push) Successful in 7m57s
CI / ci (pull_request) Successful in 7m33s
A settings change is now queued with the instant it was saved, and the
loop handles fire times up to that instant under the old rule and later
ones under the new, so a fire time the change made due is not skipped
when the scheduler gets to the change late (SCHED-01).

A failed claim no longer advances the loop past its period: the pass is
repeated every ClaimRetry until the claim succeeds, and periods already
claimed in that pass are skipped by the claim, so each runs once
(SCHED-02).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 18:41:09 -04:00
dev_agentandClaude Opus 5.5 b46192a43d Add the scheduler core with period keys and catch-up
CI / ci (pull_request) Successful in 8m2s
CI / ci (push) Successful in 8m22s
internal/scheduler runs registered schedules (a name, a daily or weekly
rule read from the household settings, and a run function) in the
household zone with an injectable clock. Each fire time's period is
claimed by inserting schedule_runs(schedule, period_key) with ON
CONFLICT DO NOTHING, so a period runs at most once across restarts and
instances. At boot only each schedule's most recent fire time is
considered: within 24 h it runs once, older it is claimed as missed so
it never runs later. Settings changes move the next fire time through
SettingsService.Subscribe. DST follows household.LocalTime. The server
starts it with the worker context and waits for it before closing the
database; the concrete schedules come in later Feature 20 tasks.

Maestro task f7024755-c3d3-46f3-b798-e242ad676c1e.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 18:17:41 -04:00