2016-08-29 12:24:48 +00:00
|
|
|
module Gitlab
|
|
|
|
module Ci
|
|
|
|
class PipelineDuration
|
|
|
|
SegmentStruct = Struct.new(:first, :last)
|
|
|
|
class Segment < SegmentStruct
|
|
|
|
def duration
|
|
|
|
last - first
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.from_builds(builds)
|
|
|
|
now = Time.now
|
|
|
|
|
|
|
|
segments = builds.map do |b|
|
2016-08-29 18:53:53 +00:00
|
|
|
Segment.new(b.started_at || now, b.finished_at || now)
|
2016-08-29 12:24:48 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
new(segments)
|
|
|
|
end
|
|
|
|
|
|
|
|
attr_reader :duration, :pending_duration
|
|
|
|
|
|
|
|
def initialize(segments)
|
|
|
|
process(segments.sort_by(&:first))
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
def process(segments)
|
|
|
|
merged = process_segments(segments)
|
|
|
|
|
|
|
|
@duration = process_duration(merged)
|
|
|
|
@pending_duration = process_pending_duration(merged, @duration)
|
|
|
|
end
|
|
|
|
|
|
|
|
def process_segments(segments)
|
|
|
|
if segments.empty?
|
|
|
|
segments
|
|
|
|
else
|
2016-08-30 15:02:39 +00:00
|
|
|
segments.drop(1).inject([segments.first]) do |result, current|
|
|
|
|
merged = try_merge_segment(result.last, current)
|
2016-08-29 12:24:48 +00:00
|
|
|
|
2016-08-30 15:02:39 +00:00
|
|
|
if merged
|
|
|
|
result[-1] = merged
|
2016-08-29 12:24:48 +00:00
|
|
|
result
|
2016-08-30 15:02:39 +00:00
|
|
|
else
|
|
|
|
result << current
|
2016-08-29 12:24:48 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-08-30 15:02:39 +00:00
|
|
|
def try_merge_segment(previous, current)
|
|
|
|
if current.first <= previous.last
|
|
|
|
Segment.new(previous.first, [previous.last, current.last].max)
|
2016-08-29 12:24:48 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def process_duration(segments)
|
|
|
|
segments.inject(0) do |result, seg|
|
|
|
|
result + seg.duration
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def process_pending_duration(segments, duration)
|
2016-08-29 15:40:15 +00:00
|
|
|
return 0 if segments.empty?
|
|
|
|
|
2016-08-29 12:24:48 +00:00
|
|
|
total = segments.last.last - segments.first.first
|
|
|
|
total - duration
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|