scheduledeploy

package
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 12, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

Documentation

Overview

Package scheduledeploy checks, on an interval, which apps have a due cron schedule (store.AppSchedule, migrations/0250_app_schedules.sql) and redeploys the latest commit on their configured branch.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ScheduleStore

type ScheduleStore interface {
	ListEnabledAppSchedules(ctx context.Context) ([]store.AppSchedule, error)
	ArmAppScheduleNextRun(ctx context.Context, serviceName string, next time.Time) error
	RecordAppScheduleHistory(ctx context.Context, e store.AppScheduleHistoryEntry) error
}

ScheduleStore is the narrow store surface Scheduler needs, re-derived fresh every tick, the same shape internal/scheduledtask.ScheduleStore's own doc comment establishes for its sibling. *store.DB satisfies this structurally.

type Scheduler

type Scheduler struct {
	Store   ScheduleStore
	Freeze  deploy.FreezeStore
	Trigger Trigger
	Logger  *slog.Logger
	// Now returns the current time; nil falls back to time.Now, the same
	// testable-clock convention every other scheduler in this codebase
	// establishes.
	Now func() time.Time
	// contains filtered or unexported fields
}

Scheduler periodically checks which app schedules are due and fires them through Trigger.

Catch-up semantics: every enabled schedule persists its own next fire time (store.AppSchedule.NextFireAt) rather than keeping it only in an in-memory position. A schedule seen for the first time (NextFireAt nil) is armed to its next real occurrence and does not fire immediately, the same "no fire on sight" rule internal/scheduledtask. Scheduler and internal/backup.Scheduler already apply to a freshly observed schedule. Once armed, Tick re-arms NextFireAt to the next occurrence strictly after now *before* calling Trigger: if the process is killed between that arm and Trigger returning, the missed firing is not retried on the next tick, and it is never fired twice either.

Because the armed time is persisted rather than kept in memory, a schedule that missed one or more occurrences entirely while the control plane was down still fires exactly once the next time it is checked, for the most recent due occurrence, never once per missed occurrence, then resumes its normal cadence from now. This is a deliberate difference from its sibling schedulers (internal/scheduledtask, internal/backup), whose in-memory position is lost on restart and which therefore never catch up a missed occurrence at all: a missed scheduled deploy is worth catching up once, a missed backup or task run is not, matching how this codebase already treats each.

A schedule due during an active deploy freeze window is skipped, not forced: it is recorded in history with a reason and re-armed for its next natural occurrence, never queued to run once the freeze lifts.

func NewScheduler

func NewScheduler(store ScheduleStore, freeze deploy.FreezeStore, trigger Trigger, logger *slog.Logger) *Scheduler

NewScheduler builds a Scheduler ready to Tick or Run. logger defaults to slog.Default() if nil.

func (*Scheduler) Run

func (s *Scheduler) Run(ctx context.Context, interval time.Duration) error

Run calls Tick on interval until ctx is done, matching the shape of every other periodic loop in this codebase (backup.Scheduler.Run, scheduledtask.Scheduler.Run, alerting.Engine.Run).

func (*Scheduler) Tick

func (s *Scheduler) Tick(ctx context.Context) error

Tick evaluates every currently enabled app schedule once. One schedule's error (an invalid cron string, Trigger itself failing) is collected and joined, never stopping evaluation of the rest, the same "one broken resource must not block the rest" principle every other scheduler in this codebase already follows.

type Trigger

type Trigger interface {
	TriggerScheduledDeploy(ctx context.Context, serviceName, branch string) (result string, err error)
}

Trigger fires a scheduled redeploy of serviceName's latest commit on branch, returning a short human-readable result recorded as the history entry's reason. *api.Router (TriggerScheduledDeploy) satisfies this; redeclared here rather than depended on directly, the same "substitutable without a real Router" reasoning internal/scheduledtask.TaskRunner's own doc comment gives for its sibling.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL