Commit aa60c7a2 authored by Matija Čupić's avatar Matija Čupić

Extract attribute caching to RedisCacheable concern

parent c92e1d73
...@@ -2,14 +2,13 @@ module Ci ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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,
......
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
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
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment