debian-mirror-gitlab/lib/gitlab/ci/runner_releases.rb

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

104 lines
2.5 KiB
Ruby
Raw Normal View History

2022-06-21 17:19:12 +05:30
# frozen_string_literal: true
module Gitlab
module Ci
class RunnerReleases
include Singleton
RELEASES_VALIDITY_PERIOD = 1.day
INITIAL_BACKOFF = 5.seconds
MAX_BACKOFF = 1.hour
BACKOFF_GROWTH_FACTOR = 2.0
def initialize
2022-08-13 15:12:31 +05:30
reset_backoff!
2022-06-21 17:19:12 +05:30
end
# Returns a sorted list of the publicly available GitLab Runner releases
#
def releases
2022-08-13 15:12:31 +05:30
return if backoff_active?
Rails.cache.fetch(
cache_key,
skip_nil: true,
expires_in: RELEASES_VALIDITY_PERIOD,
race_condition_ttl: 10.seconds
) do
response = Gitlab::HTTP.try_get(runner_releases_url)
@releases_by_minor = nil
unless response&.success?
@backoff_expire_time = next_backoff.from_now
break nil
end
reset_backoff!
extract_releases(response)
2022-08-27 11:52:29 +05:30
rescue Errno::ETIMEDOUT
@backoff_expire_time = next_backoff.from_now
break nil
2022-08-13 15:12:31 +05:30
end
end
# Returns a hash with the latest runner version per minor release
#
def releases_by_minor
return unless releases
2022-06-21 17:19:12 +05:30
2022-08-13 15:12:31 +05:30
@releases_by_minor ||= releases.group_by(&:without_patch).transform_values(&:max)
2022-06-21 17:19:12 +05:30
end
2022-08-13 15:12:31 +05:30
def reset_backoff!
@backoff_expire_time = nil
2022-06-21 17:19:12 +05:30
@backoff_count = 0
end
private
2022-08-13 15:12:31 +05:30
def runner_releases_url
@runner_releases_url ||= ::Gitlab::CurrentSettings.current_application_settings.public_runner_releases_url
end
2022-06-21 17:19:12 +05:30
2022-08-13 15:12:31 +05:30
def cache_key
runner_releases_url
end
def backoff_active?
return false unless @backoff_expire_time
Time.now.utc < @backoff_expire_time
2022-06-21 17:19:12 +05:30
end
def extract_releases(response)
2022-08-13 15:12:31 +05:30
return unless response.parsed_response.is_a?(Array)
releases = response.parsed_response
.map { |release| parse_runner_release(release) }
.select(&:valid?)
2022-08-27 11:52:29 +05:30
.sort
2022-08-13 15:12:31 +05:30
return if releases.empty? && response.parsed_response.present?
releases
2022-06-21 17:19:12 +05:30
end
def parse_runner_release(release)
2022-08-13 15:12:31 +05:30
::Gitlab::VersionInfo.parse(release['name'], parse_suffix: true)
2022-06-21 17:19:12 +05:30
end
def next_backoff
return MAX_BACKOFF if @backoff_count >= 11 # optimization to prevent expensive exponentiation and possible overflows
backoff = (INITIAL_BACKOFF * (BACKOFF_GROWTH_FACTOR**@backoff_count))
.clamp(INITIAL_BACKOFF, MAX_BACKOFF)
.seconds
@backoff_count += 1
backoff
end
end
end
end