Extract attribute caching to RedisCacheable concern
This commit is contained in:
parent
c92e1d731c
commit
aa60c7a2b5
3 changed files with 78 additions and 35 deletions
|
@ -2,14 +2,13 @@ module Ci
|
||||||
class Runner < ActiveRecord::Base
|
class Runner < ActiveRecord::Base
|
||||||
extend Gitlab::Ci::Model
|
extend Gitlab::Ci::Model
|
||||||
include Gitlab::SQL::Pattern
|
include Gitlab::SQL::Pattern
|
||||||
include Gitlab::Utils::StrongMemoize
|
include RedisCacheable
|
||||||
|
|
||||||
RUNNER_QUEUE_EXPIRY_TIME = 60.minutes
|
RUNNER_QUEUE_EXPIRY_TIME = 60.minutes
|
||||||
ONLINE_CONTACT_TIMEOUT = 1.hour
|
ONLINE_CONTACT_TIMEOUT = 1.hour
|
||||||
UPDATE_DB_RUNNER_INFO_EVERY = 40.minutes
|
UPDATE_DB_RUNNER_INFO_EVERY = 40.minutes
|
||||||
AVAILABLE_SCOPES = %w[specific shared active paused online].freeze
|
AVAILABLE_SCOPES = %w[specific shared active paused online].freeze
|
||||||
FORM_EDITABLE = %i[description tag_list active run_untagged locked access_level].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 :builds
|
||||||
has_many :runner_projects, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
|
has_many :runner_projects, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
|
||||||
|
@ -50,6 +49,8 @@ module Ci
|
||||||
ref_protected: 1
|
ref_protected: 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cached_attr_reader :version, :revision, :platform, :architecture, :contacted_at
|
||||||
|
|
||||||
# Searches for runners matching the given query.
|
# Searches for runners matching the given query.
|
||||||
#
|
#
|
||||||
# This method uses ILIKE on PostgreSQL and LIKE on MySQL.
|
# This method uses ILIKE on PostgreSQL and LIKE on MySQL.
|
||||||
|
@ -70,16 +71,6 @@ module Ci
|
||||||
ONLINE_CONTACT_TIMEOUT.ago
|
ONLINE_CONTACT_TIMEOUT.ago
|
||||||
end
|
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
|
def set_default_values
|
||||||
self.token = SecureRandom.hex(15) if self.token.blank?
|
self.token = SecureRandom.hex(15) if self.token.blank?
|
||||||
end
|
end
|
||||||
|
@ -189,10 +180,6 @@ module Ci
|
||||||
"runner:build_queue:#{self.token}"
|
"runner:build_queue:#{self.token}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def cache_attribute_key
|
|
||||||
"runner:info:#{self.id}"
|
|
||||||
end
|
|
||||||
|
|
||||||
def persist_cached_data?
|
def persist_cached_data?
|
||||||
# Use a random threshold to prevent beating DB updates.
|
# Use a random threshold to prevent beating DB updates.
|
||||||
# It generates a distribution between [40m, 80m].
|
# It generates a distribution between [40m, 80m].
|
||||||
|
@ -204,25 +191,6 @@ module Ci
|
||||||
(Time.now - real_contacted_at) >= contacted_at_max_age
|
(Time.now - real_contacted_at) >= contacted_at_max_age
|
||||||
end
|
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
|
def tag_constraints
|
||||||
unless has_tags? || run_untagged?
|
unless has_tags? || run_untagged?
|
||||||
errors.add(:tags_list,
|
errors.add(:tags_list,
|
||||||
|
|
41
app/models/concerns/redis_cacheable.rb
Normal file
41
app/models/concerns/redis_cacheable.rb
Normal file
|
@ -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
|
34
spec/models/concerns/redis_cacheable_spec.rb
Normal file
34
spec/models/concerns/redis_cacheable_spec.rb
Normal file
|
@ -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
|
Loading…
Reference in a new issue