Documentation
¶
Overview ¶
Package scheduler implements the tick loop that turns due schedules into run rows and dispatches them via the JobDispatcher.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Loop ¶
Loop runs Tick on a fixed cadence until ctx is canceled. Individual Tick errors are logged and the loop continues — only ctx cancellation or a panic stops the loop.
The first tick runs immediately at Loop start, so operators (and tests) don't wait a full cadence before seeing any scheduler activity.
Returns ctx.Err() when ctx expires.
func NextFire ¶
NextFire returns the first time > base at which the given cron expression will fire in the given IANA timezone. The returned time is in UTC.
func SweepOrphans ¶
SweepOrphans marks any non-terminal runs older than `timeout_sec + 300s` as failed with error_kind='shutdown'. Returns the number of rows updated.
Called at serve startup (to recover runs stuck when the previous process died mid-execution) and periodically from the scheduler Loop.
Types ¶
type Decision ¶
type Decision int
Decision tells the scheduler what to do with a freshly-inserted pending run.
func Decide ¶
Decide applies the overlap policy given the count of non-terminal runs for the same schedule (not including the row we just inserted).
"skip" (default) → dispatch only if no active runs; otherwise skip "queue" → dispatch only if no active runs; otherwise queue for next tick "concurrent" → always dispatch
Empty or unknown policies fail closed to the skip semantics.
Queued runs are left pending by processOne and picked up by tick.dispatchPending on a subsequent tick once prior runs finish. The split is deliberate: Tick's primary loop only walks schedules whose next_fire_at is due, so a run that was queued (and has no further scheduled fire until its cron boundary) would otherwise never get picked up. The trade-off is a one-tick latency between prior-run-finish and queued-run-dispatch; a dedicated queue-drain loop would close that gap but is not worth the complexity at MVP scale.
type Deps ¶
type Deps struct {
Pool *pgxpool.Pool
Signer *token.Signer
Dispatcher cloud.JobDispatcher
Installations InstallationTokenProvider // nil = no GitHub token injection
APIBaseURL string // e.g. "http://127.0.0.1:8080"
RunnerAPIURL string // external URL the runner uses to reach serve; falls back to APIBaseURL
RunnerBinary string // absolute path; typically os.Executable()
}
Deps bundles the scheduler's collaborators.
type InstallationTokenProvider ¶
type InstallationTokenProvider interface {
Token(ctx context.Context, installID int64) (string, error)
}
InstallationTokenProvider mints short-lived GitHub installation tokens.
type Stats ¶
Stats summarizes one Tick's effects.
func Tick ¶
Tick runs a single pass of the scheduler:
- List due schedules.
- For each: compute next_fire_at, idempotently insert a pending run, update schedule.next_fire_at.
- Apply overlap policy using the count of existing active runs.
- Dispatch via cloud.JobDispatcher when decided.
- Dispatch any already-pending rows not tied to a due schedule — manual run-now triggers and queued scheduled runs whose prior run finished.
- Run OrphanSweep to reclaim stalled runs.
Stats fields are informational for logging; errors from individual schedules are logged but don't abort the whole tick.