Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'app/models/ci/runner.rb')
-rw-r--r--app/models/ci/runner.rb74
1 files changed, 55 insertions, 19 deletions
diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb
index d12f96f3d0b..7173f88f1c7 100644
--- a/app/models/ci/runner.rb
+++ b/app/models/ci/runner.rb
@@ -1,14 +1,17 @@
module Ci
class Runner < ActiveRecord::Base
- extend Ci::Model
+ extend Gitlab::Ci::Model
+ include Gitlab::SQL::Pattern
+ include RedisCacheable
RUNNER_QUEUE_EXPIRY_TIME = 60.minutes
- LAST_CONTACT_TIME = 1.hour.ago
+ ONLINE_CONTACT_TIMEOUT = 1.hour
+ UPDATE_DB_RUNNER_INFO_EVERY = 40.minutes
AVAILABLE_SCOPES = %w[specific shared active paused online].freeze
- FORM_EDITABLE = %i[description tag_list active run_untagged locked].freeze
+ FORM_EDITABLE = %i[description tag_list active run_untagged locked access_level].freeze
has_many :builds
- has_many :runner_projects, dependent: :destroy
+ has_many :runner_projects, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_many :projects, through: :runner_projects
has_one :last_build, ->() { order('id DESC') }, class_name: 'Ci::Build'
@@ -19,7 +22,7 @@ module Ci
scope :shared, ->() { where(is_shared: true) }
scope :active, ->() { where(active: true) }
scope :paused, ->() { where(active: false) }
- scope :online, ->() { where('contacted_at > ?', LAST_CONTACT_TIME) }
+ scope :online, ->() { where('contacted_at > ?', contact_time_deadline) }
scope :ordered, ->() { order(id: :desc) }
scope :owned_or_shared, ->(project_id) do
@@ -35,11 +38,19 @@ module Ci
end
validate :tag_constraints
+ validates :access_level, presence: true
acts_as_taggable
after_destroy :cleanup_runner_queue
+ enum access_level: {
+ not_protected: 0,
+ ref_protected: 1
+ }
+
+ cached_attr_reader :version, :revision, :platform, :architecture, :contacted_at, :ip_address
+
# Searches for runners matching the given query.
#
# This method uses ILIKE on PostgreSQL and LIKE on MySQL.
@@ -53,10 +64,11 @@ module Ci
#
# Returns an ActiveRecord::Relation.
def self.search(query)
- t = arel_table
- pattern = "%#{query}%"
+ fuzzy_search(query, [:token, :description])
+ end
- where(t[:token].matches(pattern).or(t[:description].matches(pattern)))
+ def self.contact_time_deadline
+ ONLINE_CONTACT_TIMEOUT.ago
end
def set_default_values
@@ -80,7 +92,7 @@ module Ci
end
def online?
- contacted_at && contacted_at > LAST_CONTACT_TIME
+ contacted_at && contacted_at > self.class.contact_time_deadline
end
def status
@@ -102,7 +114,9 @@ module Ci
end
def can_pick?(build)
- assignable_for?(build.project) && accepting_tags?(build)
+ return false if self.ref_protected? && !build.protected?
+
+ assignable_for?(build.project_id) && accepting_tags?(build)
end
def only_for?(project)
@@ -118,11 +132,10 @@ module Ci
end
def predefined_variables
- [
- { key: 'CI_RUNNER_ID', value: id.to_s, public: true },
- { key: 'CI_RUNNER_DESCRIPTION', value: description, public: true },
- { key: 'CI_RUNNER_TAGS', value: tag_list.to_s, public: true }
- ]
+ Gitlab::Ci::Variables::Collection.new
+ .append(key: 'CI_RUNNER_ID', value: id.to_s)
+ .append(key: 'CI_RUNNER_DESCRIPTION', value: description)
+ .append(key: 'CI_RUNNER_TAGS', value: tag_list.to_s)
end
def tick_runner_queue
@@ -138,14 +151,26 @@ module Ci
expire: RUNNER_QUEUE_EXPIRY_TIME, overwrite: false)
end
- def is_runner_queue_value_latest?(value)
+ def runner_queue_value_latest?(value)
ensure_runner_queue_value == value if value.present?
end
+ def update_cached_info(values)
+ values = values&.slice(:version, :revision, :platform, :architecture, :ip_address) || {}
+ values[:contacted_at] = Time.now
+
+ cache_attributes(values)
+
+ if persist_cached_data?
+ self.assign_attributes(values)
+ self.save if self.changed?
+ end
+ end
+
private
def cleanup_runner_queue
- Gitlab::Redis.with do |redis|
+ Gitlab::Redis::Queues.with do |redis|
redis.del(runner_queue_key)
end
end
@@ -154,6 +179,17 @@ module Ci
"runner:build_queue:#{self.token}"
end
+ def persist_cached_data?
+ # Use a random threshold to prevent beating DB updates.
+ # It generates a distribution between [40m, 80m].
+
+ contacted_at_max_age = UPDATE_DB_RUNNER_INFO_EVERY + Random.rand(UPDATE_DB_RUNNER_INFO_EVERY)
+
+ real_contacted_at = read_attribute(:contacted_at)
+ real_contacted_at.nil? ||
+ (Time.now - real_contacted_at) >= contacted_at_max_age
+ end
+
def tag_constraints
unless has_tags? || run_untagged?
errors.add(:tags_list,
@@ -161,8 +197,8 @@ module Ci
end
end
- def assignable_for?(project)
- !locked? || projects.exists?(id: project.id)
+ def assignable_for?(project_id)
+ is_shared? || projects.exists?(id: project_id)
end
def accepting_tags?(build)