►
Description
Tomasz (https://about.gitlab.com/company/team/#TomaszMaczukin) and Fabio (https://about.gitlab.com/company/team/#fabiopitino) take a deep dive into the CI job schedule algorithms for GitLab CI/CD
A
A
A
A
Now,
if
the
first
first
request
for
a
job,
we
are
sending
information
how
you
can
access
the
web
terminal,
so
there
is
a
way
for
gitlab
to
connect
back
to
the
runner,
of
course,
if
it
is
configured
properly,
but
this
we
will
not
lock
on
this
time
for
for
for
scheduling
jobs,
updating
the
trace,
updating
the
job
site,
we
can
just
assume
that
it's
always
get
la
planner.
That.
A
A
Jobs
are
equivalent
yeah
of
the
very
beginning,
kita
lopsy
I
was
managing
builds
okay,
but
at
some
moments
we
decided
that
built
for
someone
maybe
make
sure
the
wrong
context,
because
it
makes
guess
that's.
It
is
all
about
building
something
so
compelling
building
images
amps
and
it's
good
luck,
SIA.
It
doesn't
limit
you
to
only
do
this.
You
can
do
in
in
this
script.
A
Is
built
is
definitely
the
job
okay,
it
was
just
not
renamed
in
the
Endicott,
so
not
focusing
now.
What
is
what
is
the
lifetime
of
the
job
we
had
such
discussions
few
weeks
ago
and
I
hope
we
will
have
some
documentation
created
from
this.
What
needs
to
be
what's
needs
to
be
known
for
the
schedule.
Inc
is
that
the
jobs
have
different
states
and.
A
A
Configuration
and
it's
in
the
first
stage,
it
may
be
a
job
in
a
not
first
stage
of
the
pipeline.
So
then
the
job
is
created
and
it
waits
until
I
get
lab,
decide
that
the
first
stage
is
finished
and
then
it
starts
all
of
the
jobs
from
the
another
stage,
and
we
have
manual
jobs
where
you
need
to
manually
click
the
start
button
or
to
API
call
to
start
a
job.
What
this.
A
Because
we
create
all
of
the
jobs
for
a
pipeline
at
once
when
creating
the
pipeline
and
and
when
you
have
a
pipeline
that
is
running,
you
can
see
this
graph
where
some
of
them
are
not
working.
They
are
there
waiting.
It's
not
only
the
graph
that
prints
what
jobs
will
be.
The
jobs
are
already
created.
The
objects
are
stored
in
the
database.
All
of
the
connections
are
made
just
the
jobs
are
in
the
created,
State
and
now
to
start
a
job.
It
may
be
done
by
three
things.
A
And
the
third
option
is
when
the
job
is
not
money
well
and
it's
in
the
first
stage
of
the
only
stage
in
the
in
the
pipeline
and
then
it
is
to
start
at
the
pipeline
start
and
what
starts
does
it?
Is
it
transitions
their
job
to
the
pending
stage,
and
this
is
for
us
important
in
context
of
of
jobs,
schedule,
because
scheduling
jobs
for
runners
is
working
only
with
jobs
that
are
being
in
the
pending
state.
B
A
Second
thing
that
is
that
is
important
to
remember
is
that
most
of
the
logic
of
C
is
implemented
in
the
raise
up
or
I,
always
say
that
runner
is
a
little
stupid
binary
that
has
on
one
job.
It
gets
a
job
definition
it
executed
and
it
reports
the
state
nothing
else,
nothing
complicated.
It,
of
course,
have
some
own
logic
about
how
the
executors
are
configured,
how
the
job
may
be
executed
in
different
stings,
but
from
the
context
of
CI.
A
Most
of
the
business
logic
is
implemented
in
the
race
and
especially
the
scheduling
part
is
implemented
in
in
wait.
So
knowing
that
we
are
working
only
with
jobs
in
pending
States,
to
think
about
scheduling,
let's
look
how
the
scheduling
works.
I
said
that
it
is
runner
but
starts
the
communication,
and
it
does
this
with
the
special
API
that
we
have
for
runners.
When
you
look
into
leap
API,
we
have
runner
dot
and
b5.
This
is
this
file
contains
the
API
used
by
the
top
runner
to
work.
Ok,
second,.
B
A
So
you
can,
you
can
get
information
about
your
runners.
You
can
have
unpause
rather
do
a
lot
of
these
things,
and
this
is.
This
is
mostly
prepared
to
be
to
be
used
by
the
users
of
the
club
and
we
are
interested
in
the
running
water,
be
because
this
is
the
definition
of
the
API
that
runner
users,
so
registration
of
new
new
runner,
requesting
a
job,
updating,
a
job,
updating
the
patched
race,
downloading
and
uploading
artifacts
in
context
of
job,
not
in
context
of
user
usage.
A
A
A
A
Github
then
knows
that
this
is
the
authorized
request
and
to
what
it
is
authorized.
So
you
try
not
to
create
a
rather
for
the
instance
level
or
for
the
project
level
for
the
group
level
in
case
of
group
and
project
it
finds,
which
group
or
which
project,
to
connect
this
one
word
and
when
the
run
is
registered.
When
it
is
connected
to
the
instance
group
for
project
it
retries,
it's
only
unique
token
that
is
saved
in
any
Rhonda's
configuration
file,
and
this
token
is
nets
next
used
to
authenticate
requests
for
new
jobs.
A
And
only
think
on
only
this
not
because
we
have
also
some
API
to
checking
if
the
runners
still
start
in
indeed
lab,
so
there
also,
this
token
is
used
because
next
updating
the
job
don't
know
the
cup
loading
artifacts.
This
is
done
with
the
CIA
job
token,
which
is
unique
for
each
job
and
it's
valid
only
when
the
job
it's
in
the
running
state.
A
A
There
is,
there
is
a
little
caching
around
around
this
end
point
because
we
have
Utley.
There
will
not
request
by
default.
It'll
appear
on
a
wheeeeel
request.
He
drop
each
three
seconds
for
for
new
jobs
and
last
year
in
every
when
I
was
checking
this,
we
had
16,000
runners
each
day
connecting
to
get
lab
each
each
of
them
I
was
creating
at
least
one
request
per
330
seconds,
so
we
have
a
huge
amount
of
such
requests
only
for
each
load
of
calm.
A
B
A
Let's,
let's
not
focus
on
this
right
now
you
can
you
can
find
where
this
last
update
is
used
here.
In
this
end
point,
you
can
look
a
little
through
it
up
workhorse.
If
you
will
need
help,
we
can.
We
can
just
jump
to
this
yet
and
go
through
walker's
code
to
see
how
the
API
is
configured
for
now.
Let's,
just
let
us
know
that
we
are
gonna,
get
love
rise
and
get
up
workout
site.
A
A
A
A
A
For
now,
we
need
to
know
that
this
executed
method-
this
is
something
that
is
that
is
being
being
executed
to
to
handle
this
this
request.
So
at
first
in
the
API
we
authenticated
the
runner
and,
while
authenticated
the
runner,
we
found
what
Runner.
This
is
exactly
which
one
runner
registers.
Indeed
lock.
This
is
passive
to
the
service,
and
here
we
are
checking
what
type
of
the
runner
pieces
because,
for
instance,
level,
so
the
showrunner.
We
have
one
query
to
the
database
for
group
level.
A
A
That
are
next,
additionally
checked
against
the
tax,
the
runner
tax
and
this
step
here
checks
if
the
jobs,
the
list
of
jobs
that
we
initially
taken
for
the
runner
that
is
asking
if
we
have,
if
we
have
any
jobs
that
are
matching
the
tax
specific
for
the
rather
do.
You
know
the
tax
field
in
the
get
lopsy
I
am
file
and.
A
You
can
you
can
park
each
runner,
for
example,
think
all
of
our
shelter
under
some
bit,
lobe,
calm,
art
act
with
the
dog
attack
and
then
in
your
github,
see
I
am
file
for
each
job.
You
can
specify
a
list
of
tax
that
needs
present
on
the
runner
to
make
it
possible
to
run
this
job.
This
is
the
way
how
you
can
define
which
runners
should
execute,
which
job?
Let's
assume
that
you
have
it,
that
you
have
a
project
where.
A
Where
the
tests
may
be
executed
on
any
platform
that
you
want,
but
the
binary
can
be
built
only
on
Windows
machine,
so
you
in
case
of
github.com,
we
don't
have
Windows
tetramers.
We
have
only
Linux
based
short
runners
and
in
your
project.
You
can
just
decide
that.
Do
you
don't
want
to
manage
your
own
runner
for
this?
You
can
just
want
to
use
the
shut
runners
that
get
logged
compromise
to
execute
some
tests.
So
you
can
just
do
nothing.
A
Shelter
under
some
key
club.com
are
configured
in
the
way
that
they
will
execute
each
job
that
doesn't
have
tax,
and
if
you
have
the
stretch
runners
enabled
in
your
project,
they
can
take
this
job
and
enter
executed.
But
for
the
compilation
your
project
requires
that
it
will
use
the
Windows
machine.
So
you
add
the
Windows
machine
to
your
project.
But
now,
if
you
have
this
Windows
machine
there,
it
may
start
catching
some
of
the
jobs
that
it
should.
Not
so
you
add
a
Windows
to
this
windows.
A
Rather,
you
add
some
tag,
for
example
windows
and
in
the
job
of
computation.
You
add
these
tags
awry
where
you
specify
windows,
the
the
rule
is
that
the
runner
needs
to
have
at
least
all
of
the
tags
that
you
specified
for
the
job
to
execute
this
job.
So
if
you
have
a
runner
which
is
target
with
Linux
docker
Ubuntu
and
in
your
job,
you
specify
a
Linux
tag,
it
will
work.
Okay,.
B
A
A
Gets
only
disre
these
jobs
that
are
matching
the
tags
of
the
runner
that
we
are
working
with,
and-
and
this
is
what
what
makes
that,
if
you
don't
have
any
available
runner
with
such
specific
tags,
no
job
will
be.
This
job
will
be
not
not
taken,
and
at
some
moment
we
will
see
in
the
UI
that
the
job
is
started,
because
you
have
no
runner
with
tax
and
there
is
the
list
of
tags
listed
in
the
in
the
unification.
A
However,
we
have
also
the
case
where
the
runner
may
be
explicitly
configure
that
this
Runner
execute
any
job
that
doesn't
have
tax
specified,
and
this
is
this
is
how
how
share
trainers
on
github.com
are
configured.
You
can
check
what
tax
we
provide
them
and
set
them
for
your
jobs,
or
you
can
do
nothing
and
just
make
sure
that
the
shift
runners
are
available,
but
for
for
some
other
runners,
we
have
this
option
disabled.
So
this
runner
will
handle
only
jobs
that
are
matching
with
the
tax
if
the
job
doesn't
have
tax.
A
This
rule
removes
the
job
from
the
list
can
pick
on
the
runner,
that's
more
or
less
the
same.
We
can
we
will
look
at
the
end
on
this
on
this
method,
what
it
does,
because
here
we
have
the
final
list
of
jobs
that
should
be
able
to
be
executed
on
the
runner,
but
requested
a
new
job.
So
we
are
iterating
over
this
list,
taking
the
first
one
which
can
be
picket
and
assign
it
to
the
run
in
case
of
a
race
condition
where
two
runners
requested
a
job.
A
In
almost
the
same
case,
two
runners,
who
are
so
equal
that
the
same
jobs
were
taken
into
the
list
and
two
runners
will
take
the
same
job
of
the
first
one.
We
have
the
transactions
and
and
the
first
one
which
will
in
the
milliseconds
we
in
this
compared
with
this
competition,
will
obviously
lock
the
transition
transaction,
be
assign
and
update
the
state
to
running
the
second
one
will
receive
one
of
these
two
exceptions
and.
B
A
This
case
to
just
speed
up
the
thing
we
are
allowing
the
loop
to
be
executed
once
again,
so
if
we
had
an
exception
only
because
there
was
a
race
condition,
we
try
to
assign
the
job
another
from
the
list
to
this,
rather
to
just
not
require
another
request
mate
in
case.
If
such
situation
would
be
repeated,
we
return
an
error
and
then
the
runner
need
to
do
a
request
again.
So,
let's,
let's
maybe
walk
on
this-
can
pick
it
basically
checks.
B
A
In
that
case,
the
runner
needs
to
be
needs
to
be
maybe
I
know
in
the
opposite
thing.
If
you
mark
the
runner
as
protected,
then
it
will
execute
only
jobs
on
the
protected
branch
of
syntax
only
thing
so
you
can
have,
for
example,
who
the
runner
that
is
dying,
doing
production
deployment,
and
you
don't
want
anyone
with
access
to
the
project
to
be
able
to
start
the
job.
You
want
to
only
have
some
some
users
that
you
trust
to
be
able
to
do
this,
so
you
made
them
make
the
maintainer
in
the
projects.
A
A
So
if
the
runner
is
a
project
runner,
we
get
the
list
of
projects
assigned
to
this
runner.
We
are
removing
from
it
all
projects
that
are
pending
deleted
and
all
projects
where
the
pipeline's
feature
is
not
enabled
we
have.
We
then
get
new
deals.
It's
also
what
we
need
to
look
on,
because
we
are
looking
on
ending
and
unstarted
jobs
and
in
case
of
of
the
protected
runner,
we
are
looking
on
also
on
the
jobs
that
are
marketed
as
protected
and
then
in
case
of
projects.
A
A
If
you
will
shake
this
query,
analyse
what
it
is
doing.
We
basically
prioritize
jobs
from
projects
that
are
at
this
moment,
not
using
sheet
runners.
For
example,
you
have
a
project
and
I
have
a
project,
you
push
it
something
that
created
thousands
of
jobs
and
the
shelter
handles
that
we
have
on
our
lead.
A
A
If
you
have
some
jobs,
then
you're
put
it
in
the
list,
depending
on
how
many
jobs
you
already
have
from
the
Shadrin
and
then
in
this
list
we
again
order
these
by
the
ID
of
the
jobs.
So
if
you
push
it
hundred
of
the
jobs
and
I
push
it
ten
of
the
jobs
in
very
simple
scenario,
it
should
be
done
like
gitlab
will
assign
for
each
every
query
from
the
runner.
It
will
assign
your
job
number
one.
A
My
job
number
one,
your
job
number,
two,
my
job
number,
two,
your
job
number
three,
my
job
number
three
up
to
ten
and
then
because
you
have
steel
jobs,
I
have
no
jobs
left
and
there
is
no
other
jobs
in
this
get
lab.
It
will
be
able
to
assign
your
job
number
eleven.
Twelve
thirteen
fourteen,
that's
okay,.
B
A
A
When
you
have
this
for
your
groups,
you
don't
fight
again
this
resource,
because
this
is
your
resource
for
the
sheet
runners.
We
want
to
make
it
available
for
all
users
on
the
guillotines,
so
this
is
how
how
this
is
implemented
here.
We
have
also
some
metrics
that
are
tracked
during
the
job
scheduling
and
what
needs
to
be
remembered
is
that
it's
runner
that
creates
the
request
and
asks
for
a
job
if
you
will
disable
all
around,
maybe
not
disable.
A
A
A
B
A
If,
if
there
is
no
request
from
runners,
no
jobs
are
scheduled,
because
this
is
the
basic
requirement
there
needs
to
be
a
runner
that
will
ask
for
it.
When
the
runner
is
asking
for
the
job.
We
are
first
checking
which
type
of
the
runner
basis,
and
then
we
are
creating
a
basic
list
of
jobs
dependent
on
what
runner
asked
it
for
it.
In
case
of
runner,
we
are
trying
to
fail.
Miss
distribute
this
among
all
of
the
projects.
A
Group
projects
is
allowed
in
this
case
and
we
are
limiting
filtering
all
of
the
jobs
that
are
not
meeting
the
requirements
putting
them
off,
and
then
we
have
the
final
list
of
jobs
ordered
from
the
oldest
one,
and
we
are
trying
to
schedule
for
this
request.
The
first
one
from
the
list,
but
in
case
when
you
have
more
than
one
runner.
A
It
finally
ends
that
we
have
the
assigning
quite
random.
If
you
have,
if
you
have
in
your
project,
future
runners
that
are
enabled
and
are
matching
all
of
the
requirements
for
the
job.
If
you
have
additionally
few
project
rubber
runners
runners
that
are
also
matching
this
job-
and
you
have
few
group
Rev
level
runners
on
different
groups
that
your
project
belongs
to.
B
B
The
kill
you
all
use
in
the
workspace
yes,
so
that
means
that,
rather
than
assigning
the
first,
let
register
success
and
then
return
the
result.
We
might
need
to
do
something
there.
We
actually
we
don't
exit
the
build,
but
we
try
to
schedule
all
the
possible
jobs
we
can
give
to
this
runner.
It
can
be
a
little
bit
complicated
and
I.
Guess
yes,.
A
A
B
So
yeah,
it
looks
like
that
we
will
have
events
and
correctly
like
scenarios
where
the
jobs,
apart
from
the
one
that
is
currently
the
chemical
it
will
be
handled
by
the
runner.
That
will
be
the
only
one
pending.
We
have
other
jobs
down
the
line
that
will
be
still
in
created
state
but
somehow
already
assigned
to
to
a
runner,
so
that
mix
next
time
the
run
when
the
runner
finished
the
first
job
requests
the
next
job.
It
will
simply
trigger
a
change
in
the
state
machine
from
created
to
pending,
but
it
will.
A
Don't
don't
don't
mess
the
the
states
the
created
depending
is
done
by
github,
and
if
this
this
is
what
needs
to
be
done
to
even
make
this
job
visible
for
the
run
runner
when
requesting
for
job
is
transitioning
the
job
from
pending
tronic
yep.
So
so,
finally,
we
will
have
a
list
of
jobs
in
pending
state
that
are
already
assigned
to
some
run.
Not
increased.
Okay,
I
see
I,
see
because,
because,
if
job
is
in
created
state
that
runner
will
not
get
it
because
I.
B
A
Only
created
so
so
so
transitioning
from
created
pending
will
be
happening
like
it's
happening
now.
When,
when
the
job
is
manual,
you
will
need
to
trigger
this
by
hand
API
or
by
the
button.
When
the
job
is
not
manual,
then
in
the
first
stage
it
will
be
started
automatically
in
each
next
stage.
It
will
wait
until
gitlab
will
decide
that
the
first
stage
the
previous
stage
was
fully
finished.
A
B
So
if,
but
it
seems
like,
we
can't
change
all
the
jobs
that
could
be
assigned
for
a
specific
workspace.
There
are
all
part
of
the
same
workspace.
We
can
change
them
all
into
pending
at
one
time,
because
we
might
risk
to
pick
jobs
there
later
down
the
line
and
assign
to
to
the
runner
right
what
we
want
to
still
what
kind
of
a
sequence
of
the
events
yes,.
A
A
Don't
know
I,
don't
know
how
we'll
just
go
with
with
go
workspaces
there
two
to
two
possible
ways:
we
allow
you
to
configure
multiple
jobs
in
one
by
one
pipeline
stage,
but
then
we'll
need
to
get
them
and
order
them
sequentially.
So
you
have
hundred
parallel
jobs
that
are
executed
synchrotron.
The
other
case
is
that
we
will
not
allow
to
create
two
parallel
jobs
assigned
to
the
same
workspace
at
the
same
time,
but
this
is
this
is
a
different
level
of
how
we
will
handle
the
workspace
from
the
runners
side.
A
A
B
A
A
moment
I
will
send
you
the
documentation
page
where
the
first
scheduling
algorithm
is
described.
Okay,
when
looking
on
the
query
and
on
the
documentation
description,
it
may
be
a
little
easier
to
understand
the
query.
The
query
when
you
will
execute
this
on
your
walk
out,
get
love
development
instance.
The
cube
query
is
yeah.
The
analyze
analyze
form
from
phosphorus
is
I
hope
in
looping
looping.
It
has.