Add the scheduler core with period keys and catch-up
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>
This commit is contained in:
+14
-2
@@ -30,6 +30,7 @@ import (
|
||||
"code.cubecraftlabs.com/Maniacs_Mansion/Meal-Quest/internal/plan"
|
||||
"code.cubecraftlabs.com/Maniacs_Mansion/Meal-Quest/internal/push"
|
||||
"code.cubecraftlabs.com/Maniacs_Mansion/Meal-Quest/internal/recipes"
|
||||
"code.cubecraftlabs.com/Maniacs_Mansion/Meal-Quest/internal/scheduler"
|
||||
"code.cubecraftlabs.com/Maniacs_Mansion/Meal-Quest/internal/secretbox"
|
||||
"code.cubecraftlabs.com/Maniacs_Mansion/Meal-Quest/internal/server"
|
||||
"code.cubecraftlabs.com/Maniacs_Mansion/Meal-Quest/internal/shopping"
|
||||
@@ -187,17 +188,23 @@ func run(cfg config.Config, logger *slog.Logger) error {
|
||||
return err
|
||||
}
|
||||
|
||||
sched, err := scheduler.New(db, settings, logger)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
router, err := server.NewRouter(logger, version, cfg.TrustedProxy, authFlow, sessions, settings, search, ai, chatSvc, dinnerSvc, suggestSvc, planSvc, shopSvc, googleSvc, pushSvc, ideasSvc, runner, photos, frontend.Assets())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Start fails the jobs a previous process left running before any
|
||||
// worker runs. The job workers and the notification worker stop, and
|
||||
// are waited for, before the database closes.
|
||||
// worker runs. The job workers, the notification worker and the
|
||||
// scheduler stop, and are waited for, before the database closes.
|
||||
workersCtx, stopWorkers := context.WithCancel(ctx)
|
||||
defer func() {
|
||||
stopWorkers()
|
||||
sched.Wait()
|
||||
runner.Wait()
|
||||
notifier.Wait()
|
||||
}()
|
||||
@@ -213,6 +220,11 @@ func run(cfg config.Config, logger *slog.Logger) error {
|
||||
if _, err := dinnerSvc.FailInterruptedGroundings(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
// The scheduler starts last: its catch-up may enqueue jobs and
|
||||
// notifications, so their workers must already run.
|
||||
if err := sched.Start(workersCtx); err != nil {
|
||||
return err
|
||||
}
|
||||
srv := &http.Server{
|
||||
Addr: cfg.HTTPAddr,
|
||||
Handler: router,
|
||||
|
||||
Reference in New Issue
Block a user