Skip to main content

Module scheduler

Module scheduler 

Source
Expand description

Which runners to start and stop, as a pure function of queued jobs, slots, warm runners and the memory and CPU budgets (plan), how many warm runners each repository wants (warm), and the loop that applies those decisions with GitHub and Docker (engine). plan and warm do no I/O and read no clock.

Modules§

engine
The scheduling loop: polls GitHub, pulls the profiles’ images, applies plan’s decisions with GitHub and Docker, removes each runner’s container when its job ends, keeps the mirror up while any runner runs, reseeds idle profiles and recovers runners and containers a previous daemon left. It also feeds the job history: queued jobs, the job each runner took (from observe::capture), steps from GitHub, mirror bytes, cache sizes and slot and budget changes. It owns slot state; it never serves the API (it publishes api::Status and takes commands through Control) and never logs the token or a JIT config.
warm
How many warm runners each repository wants (ADR 0050): its warm while it is active, by its jobs of the last hour and the hours of the day its jobs usually come, plus the jobs its workflow runs seen so far are expected to queue still, from the history. Pure: the engine reads the history and the clock and passes them in.

Structs§

Budget
The budgets a plan starts runners within.
Hold
A repository’s runners held back after they failed.
Plan
What plan decides, and why each queued job it starts no runner for waits.
Profile
A profile’s slots: one concurrent job each.
Repository
A repository as the planner sees it.
RunnerSlot
A slot whose container runs a runner registered for one job.
SlotRef
Where slots are, by profile name and slot index (0 is slot 1).

Enums§

Decision
What plan decides for one slot.
Preparing
Why none of a profile’s slots starts for now.
Slot
What a slot holds.

Constants§

CPU_PRIORITY_AFTER
Once a job has waited this long for CPU, no younger job takes CPU until it fits: smaller jobs arriving all the time would otherwise take every CPU that frees up before it.
IDLE_TIMEOUT
How long a started runner may wait for a job before it counts as surplus: covers the container’s start and GitHub’s assignment.

Functions§

matches
Whether a job may run on a repository’s runners: every label it asks for is one of theirs. GitHub compares labels without regard to case.
plan
Decides which slots start a runner and which idle runners stop, and why each job left queued waits.