summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/models/ci/runner.rb38
-rw-r--r--app/models/concerns/redis_cacheable.rb41
-rw-r--r--spec/models/concerns/redis_cacheable_spec.rb34
3 files changed, 78 insertions, 35 deletions
diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb
index 6bd90e71bf3..f6db71be438 100644
--- a/app/models/ci/runner.rb
+++ b/app/models/ci/runner.rb
@@ -2,14 +2,13 @@ module Ci
class Runner < ActiveRecord::Base
extend Gitlab::Ci::Model
include Gitlab::SQL::Pattern
- include Gitlab::Utils::StrongMemoize
+ include RedisCacheable
RUNNER_QUEUE_EXPIRY_TIME = 60.minutes
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 access_level].freeze
- CACHED_ATTRIBUTES_EXPIRY_TIME = 24.hours
has_many :builds
has_many :runner_projects, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
@@ -50,6 +49,8 @@ module Ci
ref_protected: 1
}
+ cached_attr_reader :version, :revision, :platform, :architecture, :contacted_at
+
# Searches for runners matching the given query.
#
# This method uses ILIKE on PostgreSQL and LIKE on MySQL.
@@ -70,16 +71,6 @@ module Ci
ONLINE_CONTACT_TIMEOUT.ago
end
- def self.cached_attr_reader(*attributes)
- attributes.each do |attribute|
- define_method("#{attribute}") do
- cached_attribute(attribute) || read_attribute(attribute)
- end
- end
- end
-
- cached_attr_reader :version, :revision, :platform, :architecture, :contacted_at
-
def set_default_values
self.token = SecureRandom.hex(15) if self.token.blank?
end
@@ -189,10 +180,6 @@ module Ci
"runner:build_queue:#{self.token}"
end
- def cache_attribute_key
- "runner:info:#{self.id}"
- end
-
def persist_cached_data?
# Use a random threshold to prevent beating DB updates.
# It generates a distribution between [40m, 80m].
@@ -204,25 +191,6 @@ module Ci
(Time.now - real_contacted_at) >= contacted_at_max_age
end
- def cached_attribute(key)
- (cached_attributes || {})[key]
- end
-
- def cached_attributes
- strong_memoize(:cached_attributes) do
- Gitlab::Redis::SharedState.with do |redis|
- data = redis.get(cache_attribute_key)
- JSON.parse(data, symbolize_names: true) if data
- end
- end
- end
-
- def cache_attributes(values)
- Gitlab::Redis::SharedState.with do |redis|
- redis.set(cache_attribute_key, values.to_json, ex: CACHED_ATTRIBUTES_EXPIRY_TIME)
- end
- end
-
def tag_constraints
unless has_tags? || run_untagged?
errors.add(:tags_list,
diff --git a/app/models/concerns/redis_cacheable.rb b/app/models/concerns/redis_cacheable.rb
new file mode 100644
index 00000000000..249ebf9af07
--- /dev/null
+++ b/app/models/concerns/redis_cacheable.rb
@@ -0,0 +1,41 @@
+module RedisCacheable
+ extend ActiveSupport::Concern
+ include Gitlab::Utils::StrongMemoize
+
+ CACHED_ATTRIBUTES_EXPIRY_TIME = 24.hours
+
+ class_methods do
+ def cached_attr_reader(*attributes)
+ attributes.each do |attribute|
+ define_method("#{attribute}") do
+ cached_attribute(attribute) || read_attribute(attribute)
+ end
+ end
+ end
+ end
+
+ def cached_attribute(attribute)
+ (cached_attributes || {})[attribute]
+ end
+
+ def cache_attributes(values)
+ Gitlab::Redis::SharedState.with do |redis|
+ redis.set(cache_attribute_key, values.to_json, ex: CACHED_ATTRIBUTES_EXPIRY_TIME)
+ end
+ end
+
+ private
+
+ def cache_attribute_key
+ "#{self.class.name}:attributes:#{self.id}"
+ end
+
+ def cached_attributes
+ strong_memoize(:cached_attributes) do
+ Gitlab::Redis::SharedState.with do |redis|
+ data = redis.get(cache_attribute_key)
+ JSON.parse(data, symbolize_names: true) if data
+ end
+ end
+ end
+end
diff --git a/spec/models/concerns/redis_cacheable_spec.rb b/spec/models/concerns/redis_cacheable_spec.rb
new file mode 100644
index 00000000000..3edb69f4666
--- /dev/null
+++ b/spec/models/concerns/redis_cacheable_spec.rb
@@ -0,0 +1,34 @@
+require 'spec_helper'
+
+describe RedisCacheable do
+ let(:runner) { build(:ci_runner) }
+
+ describe '#cached_attribute' do
+ subject { runner.cached_attribute(:anything) }
+
+ it 'gets the cache attribute' do
+ Gitlab::Redis::SharedState.with do |redis|
+ expect(redis).to receive(:get).with(runner.send(:cache_attribute_key))
+ end
+
+ subject
+ end
+ end
+
+ describe '#cache_attributes' do
+ let(:values) { { name: 'new_name' } }
+
+ subject { runner.cache_attributes(values) }
+
+ it 'sets the cache attributes' do
+ Gitlab::Redis::SharedState.with do |redis|
+ values.each do |key, value|
+ redis_key = runner.send(:cache_attribute_key)
+ expect(redis).to receive(:set).with(redis_key, values.to_json, anything)
+ end
+ end
+
+ subject
+ end
+ end
+end