Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/git/vole.git

Write over SSH with a registered key:

git clone ssh://git@0.0.0.0:2222/vole.git

A free and open-source forge that lives in your Git repo.

Run several jobs at once with --jobs

18c559ea0010dc22db13c889afda4fe9af3c15d7 · Keenan Nemetz · 2d ago · parent 91b47a22

Run several jobs at once with --jobs

A runner process leased one job and blocked on it, so the only way to get a
second job onto a machine was a second process: another host, another key,
another allowlist entry, and another --dir that learns the repositories cold.
The server was never the limit — a lease is taken per session and claimed by a
conditional update — so this is the runner catching up.

`--jobs N` is N slots in one process. Each slot owns a session and runs at most
one job, and everything that belongs to the process happens once, before the
slots start: the directories, the cache bounds, the leftover sweep, and the
connections. A slot that refuses a job stops every slot, because reconnecting
would ask the same instance the same question. A slot that loses its connection
reconnects with a doubling delay instead, so one flaky link does not take the
other slots' jobs with it; the job it was running is requeued when its lease
expires.

The log stream moves from the session to the job, which is what makes two jobs
on one session impossible to confuse: a slot has one, and it is the stream for
the job in front of it.

Deployment: `RUNNER_JOBS` in the first-boot renderer, the packaged argument
file, and the docs. The container limits are per job, so the machine has to
carry --jobs times what they allow; max_jobs_per_repo is what stops one
repository claiming every slot.

Refs: 01M6SCWCSX39QXS38QAHQSMVGX (#216)

docs/runner.md +40−2

@@ -30,9 +30,47 @@ vole runner --remote ssh://git@host:2222 --repos demo --repos docs
30 30 - `--repos` narrows what the account is already allowed to run. It cannot grant
31 31 access to a repository.
32 32 - `--dir` chooses where checkouts and caches are kept.
33 - `--jobs` is how many jobs this machine runs at once. Each gets its own container;
34 see [Running several jobs at once](#running-several-jobs-at-once).
33 35 - `--once` leases one job and exits, which is useful for a runner that is
34 36 scheduled per job.
35 37
38 ## Running several jobs at once
39
40 A build is usually one step waiting on one thing at a time, so most of a big machine
41 sits idle behind it. `--jobs` puts more jobs on the one machine:
42
43 ```sh
44 vole runner --remote ssh://git@host:2222 --container-runtime podman --jobs 4
45 ```
46
47 Each job slot is a session of its own, so the instance hands work to each one
48 independently and the runners page shows four rows rather than one. The slots share
49 the machine: one cache, one set of saved checkouts, one set of images. What they do
50 not share is a container.
51
52 Two things need sizing for it:
53
54 - **The container limits are per job.** `--container-memory`, `--container-cpus` and
55 `--container-pids` apply to each container, so a machine running four jobs needs
56 four times what they allow. On the instance, `max_jobs_per_repo` is what stops one
57 repository's burst from claiming every slot (see
58 [Configuration](configuration.md)).
59 - **A job's cache is shared with the same repository's other jobs.** Two jobs of the
60 same repository, trust and image get the same `/cache`, which is what lets them
61 reuse each other's downloads. The tools in the image are what make that safe: `go`,
62 `cargo` and `npm` all lock their own caches. A job that empties `/cache` or keeps
63 state there between runs is competing with its own siblings, so give it a path of
64 its own or its own runner.
65
66 An idle slot holds one open connection while it waits for work, so a machine with
67 `--jobs 8` uses eight of the instance's SSH connections (`ssh_max_connections`).
68 Losing a connection costs that slot its job — the job is requeued when its lease
69 expires — and the slot reconnects rather than stopping the rest.
70
71 With `--once`, `--jobs 4` starts up to four jobs, finishes them, and exits, which is
72 the shape a scheduler that starts a container per job wants.
73
36 74 ## The runner's account
37 75
38 76 A runner connects as an account, and that account is the runner's identity: it is
@@ -140,8 +178,8 @@ instance or kept on the runner, so each of those channels has a bound:
140 178 checkouts jobs clone from are bounded separately; see
141 179 [Saved checkouts](#saved-checkouts).
142 180 - **Container.** `--container-memory`, `--container-cpus` and `--container-pids`
143 pass the runtime's own limits. `--container-network` is what this machine can
144 offer — `none` (the default) or `bridge` — and a job's own `network:` decides what
181 pass the runtime's own limits, per container, so `--jobs` multiplies them.
182 `--container-network` is what this machine can offer — `none` (the default) or `bridge` — and a job's own `network:` decides what
145 183 it gets, so a bridge runner can still run a job that asks for none. See
146 184 [Network](#network). The runtime's storage driver, not Vole, is what bounds the
147 185 container's writable layer, so size it on the host.