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/vole.git

Write over SSH with a registered key:

git clone ssh://git@rodent.software:2222/vole.git

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

Build one image-file digest once per runner process

77056ba834ba243104726b91e7ff19498d4e8337 · Keenan Nemetz · 3d ago · parent 18c559ea

Build one image-file digest once per runner process

Two slots leased jobs that name the same image-file and both built it: the same
bytes, the same tag, twice the CPU and twice the disk, with two runtimes racing
to tag the result. The first slot now builds it and the others wait on the same
answer, which is shared by the process rather than by the session, because that
is what --jobs is.

Waiting is not free: a build can run for half an hour, and a runner that stops
heartbeating loses the run it is holding. So a waiter heartbeats on the same
beat its own build would have, and stops if the lease goes away or a maintainer
cancels the run. A failed build fails the jobs waiting on it, since the same
definition would fail the same way.

Two runner processes sharing a --dir can still both build the digest. That is
waste, not damage: the definition is pinned by digest, so both builds produce
the same image under the same tag, and serialising that too would mean a lock
file per digest beside the caches.

Refs: 01M6SCWCSX39QXS38QAHQSMVGX (#216)

ci/agent/sandbox.go +7−1

@@ -32,11 +32,16 @@ import (
32 32 )
33 33
34 34 // runnerBox is the validated container settings plus the identity this runner
35 // process uses to find containers a killed predecessor left behind.
35 // process uses to find containers a killed predecessor left behind, and the builds
36 // it has in flight.
36 37 type runnerBox struct {
37 38 container.Config
38 39 id string
39 40 pid int
41 // builds is shared by every slot in the process, so two jobs that name the same
42 // image-file build it once. Nil means the caller never validated these options,
43 // which only a test does.
44 builds *imageBuilds
40 45 }
41 46
42 47 // containerOptions validates the runner's container settings and fills in the
@@ -64,6 +69,7 @@ func containerOptions(opts Options, cache string) (runnerBox, error) {
64 69 Config: cfg,
65 70 id: fmt.Sprintf("%x", sum[:6]),
66 71 pid: os.Getpid(),
72 builds: &imageBuilds{},
67 73 }, nil
68 74 }
69 75