Forget about pending duration for now, need more discussion
This commit is contained in:
parent
7aaed299eb
commit
d071f61b0d
|
@ -260,8 +260,7 @@ module Ci
|
||||||
def update_duration
|
def update_duration
|
||||||
return unless started_at
|
return unless started_at
|
||||||
|
|
||||||
self.duration, self.pending_duration =
|
self.duration = Gitlab::Ci::PipelineDuration.from_pipeline(self)
|
||||||
Gitlab::Ci::PipelineDuration.from_pipeline(self)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def execute_hooks
|
def execute_hooks
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
class AddPendingDurationToPipelines < ActiveRecord::Migration
|
|
||||||
DOWNTIME = false
|
|
||||||
|
|
||||||
def change
|
|
||||||
add_column :ci_commits, :pending_duration, :integer
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -210,7 +210,6 @@ ActiveRecord::Schema.define(version: 20160831223750) do
|
||||||
t.datetime "finished_at"
|
t.datetime "finished_at"
|
||||||
t.integer "duration"
|
t.integer "duration"
|
||||||
t.integer "user_id"
|
t.integer "user_id"
|
||||||
t.integer "pending_duration"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
add_index "ci_commits", ["gl_project_id", "sha"], name: "index_ci_commits_on_gl_project_id_and_sha", using: :btree
|
add_index "ci_commits", ["gl_project_id", "sha"], name: "index_ci_commits_on_gl_project_id_and_sha", using: :btree
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
module Gitlab
|
module Gitlab
|
||||||
module Ci
|
module Ci
|
||||||
|
# # Introduction - total running time
|
||||||
|
#
|
||||||
# The problem this class is trying to solve is finding the total running
|
# The problem this class is trying to solve is finding the total running
|
||||||
# time amongst all the jobs, excluding retries and pending (queue) time.
|
# time amongst all the jobs, excluding retries and pending (queue) time.
|
||||||
# We could reduce this problem down to finding the union of periods.
|
# We could reduce this problem down to finding the union of periods.
|
||||||
#
|
#
|
||||||
# So each job would be represented as a `Period`, which consists of
|
# So each job would be represented as a `Period`, which consists of
|
||||||
# `Period#first` and `Period#last`. A simple example here would be:
|
# `Period#first` as when the job started and `Period#last` as when the
|
||||||
|
# job was finished. A simple example here would be:
|
||||||
#
|
#
|
||||||
# * A (1, 3)
|
# * A (1, 3)
|
||||||
# * B (2, 4)
|
# * B (2, 4)
|
||||||
|
@ -24,22 +27,7 @@ module Gitlab
|
||||||
#
|
#
|
||||||
# (4 - 1) + (7 - 6) => 4
|
# (4 - 1) + (7 - 6) => 4
|
||||||
#
|
#
|
||||||
# And the pending (queue) time would be (4, 6) like this: (marked as X)
|
# # The Algorithm
|
||||||
#
|
|
||||||
# 0 1 2 3 4 5 6 7
|
|
||||||
# AAAAAAA
|
|
||||||
# BBBBBBB
|
|
||||||
# CCCC
|
|
||||||
# XXXXX
|
|
||||||
#
|
|
||||||
# Which could be calculated by having (1, 7) as total time, minus
|
|
||||||
# the running time we have above, 4. The full calculation would be:
|
|
||||||
#
|
|
||||||
# total = (7 - 1)
|
|
||||||
# duration = (4 - 1) + (7 - 6)
|
|
||||||
# pending = total - duration # 6 - 4 => 2
|
|
||||||
#
|
|
||||||
# Which the answer to pending would be 2 in this example.
|
|
||||||
#
|
#
|
||||||
# The algorithm used here for union would be described as follow.
|
# The algorithm used here for union would be described as follow.
|
||||||
# First we make sure that all periods are sorted by `Period#first`.
|
# First we make sure that all periods are sorted by `Period#first`.
|
||||||
|
@ -82,22 +70,12 @@ module Gitlab
|
||||||
# `C.first <= D.last` is `false`. Therefore we need to keep both C
|
# `C.first <= D.last` is `false`. Therefore we need to keep both C
|
||||||
# and D. The example would end here because there are no more jobs.
|
# and D. The example would end here because there are no more jobs.
|
||||||
#
|
#
|
||||||
# After having the union of all periods, the rest is simple and
|
# After having the union of all periods, we just need to sum the length
|
||||||
# described in the beginning. To summarise:
|
# of all periods to get total time.
|
||||||
#
|
#
|
||||||
# duration = (4 - 1) + (7 - 6)
|
# (4 - 1) + (7 - 6) => 4
|
||||||
# total = (7 - 1)
|
|
||||||
# pending = total - duration # 6 - 4 => 2
|
|
||||||
#
|
#
|
||||||
# Note that the pending time is actually not the final pending time
|
# That is 4 is the answer in the example.
|
||||||
# for pipelines, because we still need to accumulate the pending time
|
|
||||||
# before the first job (A in this example) even started! That is:
|
|
||||||
#
|
|
||||||
# total_pending = pipeline.started_at - pipeline.created_at + pending
|
|
||||||
#
|
|
||||||
# Would be the final answer. We deal with that in pipeline itself
|
|
||||||
# but not here because here we try not to be depending on pipeline
|
|
||||||
# and it's trivial enough to get that information.
|
|
||||||
class PipelineDuration
|
class PipelineDuration
|
||||||
PeriodStruct = Struct.new(:first, :last)
|
PeriodStruct = Struct.new(:first, :last)
|
||||||
class Period < PeriodStruct
|
class Period < PeriodStruct
|
||||||
|
@ -107,17 +85,10 @@ module Gitlab
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.from_pipeline(pipeline)
|
def self.from_pipeline(pipeline)
|
||||||
now = Time.now
|
|
||||||
status = %w[success failed running canceled]
|
status = %w[success failed running canceled]
|
||||||
builds = pipeline.builds.latest.where(status: status)
|
builds = pipeline.builds.latest.where(status: status)
|
||||||
|
|
||||||
running = from_builds(builds, :started_at, :finished_at, now).duration
|
from_builds(builds, :started_at, :finished_at).duration
|
||||||
pending = pipeline.started_at - pipeline.created_at
|
|
||||||
queuing = builds.inject(0) do |result, job|
|
|
||||||
result + ((job.started_at || now) - (job.queued_at || now))
|
|
||||||
end
|
|
||||||
|
|
||||||
[running, pending + queuing]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.from_builds(builds, from, to, now = Time.now)
|
def self.from_builds(builds, from, to, now = Time.now)
|
||||||
|
|
Loading…
Reference in New Issue