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

Move info update implementation to Ci::Runner model

parent 92ac2b9e
...@@ -5,6 +5,7 @@ module Ci ...@@ -5,6 +5,7 @@ module Ci
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 = 1.hour
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
...@@ -89,7 +90,7 @@ module Ci ...@@ -89,7 +90,7 @@ module Ci
def online? def online?
Gitlab::Redis::SharedState.with do |redis| Gitlab::Redis::SharedState.with do |redis|
last_seen = redis.get("#{self.runner_info_key}:contacted_at") || contacted_at last_seen = redis.get("#{runner_info_redis_cache_key}:contacted_at") || contacted_at
last_seen && last_seen > self.class.contact_time_deadline last_seen && last_seen > self.class.contact_time_deadline
end end
end end
...@@ -155,8 +156,16 @@ module Ci ...@@ -155,8 +156,16 @@ module Ci
ensure_runner_queue_value == value if value.present? ensure_runner_queue_value == value if value.present?
end end
def runner_info_key def update_runner_info(params)
"runner:info:#{self.id}" update_runner_info_cache
# Use a 1h threshold to prevent beating DB updates.
return unless self.contacted_at.nil? ||
(Time.now - self.contacted_at) >= UPDATE_DB_RUNNER_INFO_EVERY
self.contacted_at = Time.now
self.assign_attributes(params)
self.save if self.changed?
end end
private private
...@@ -171,6 +180,17 @@ module Ci ...@@ -171,6 +180,17 @@ module Ci
"runner:build_queue:#{self.token}" "runner:build_queue:#{self.token}"
end end
def runner_info_redis_cache_key
"runner:info:#{self.id}"
end
def update_runner_info_cache
Gitlab::Redis::SharedState.with do |redis|
redis_key = "#{runner_info_redis_cache_key}:contacted_at"
redis.set(redis_key, Time.now)
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,
......
...@@ -5,7 +5,6 @@ module API ...@@ -5,7 +5,6 @@ module API
JOB_TOKEN_HEADER = 'HTTP_JOB_TOKEN'.freeze JOB_TOKEN_HEADER = 'HTTP_JOB_TOKEN'.freeze
JOB_TOKEN_PARAM = :token JOB_TOKEN_PARAM = :token
UPDATE_RUNNER_EVERY = 10 * 60
def runner_registration_token_valid? def runner_registration_token_valid?
ActiveSupport::SecurityUtils.variable_size_secure_compare(params[:token], ActiveSupport::SecurityUtils.variable_size_secure_compare(params[:token],
...@@ -21,37 +20,13 @@ module API ...@@ -21,37 +20,13 @@ module API
def authenticate_runner! def authenticate_runner!
forbidden! unless current_runner forbidden! unless current_runner
update_runner_info current_runner.update_runner_info(get_runner_version_from_params)
end end
def current_runner def current_runner
@runner ||= ::Ci::Runner.find_by_token(params[:token].to_s) @runner ||= ::Ci::Runner.find_by_token(params[:token].to_s)
end end
def update_runner_info
update_runner_info_cache
return unless update_runner?
current_runner.contacted_at = Time.now
current_runner.assign_attributes(get_runner_version_from_params)
current_runner.save if current_runner.changed?
end
def update_runner?
# Use a 1h threshold to prevent beating DB updates.
current_runner.contacted_at.nil? ||
(Time.now - current_runner.contacted_at) >= UPDATE_RUNNER_EVERY
end
def update_runner_info_cache
Gitlab::Redis::SharedState.with do |redis|
redis_key = "#{current_runner.runner_info_key}:contacted_at"
redis.set(redis_key, Time.now)
end
end
def validate_job!(job) def validate_job!(job)
not_found! unless job not_found! unless job
......
...@@ -97,7 +97,7 @@ describe Ci::Runner do ...@@ -97,7 +97,7 @@ describe Ci::Runner do
context 'no cache value' do context 'no cache value' do
before do before do
stub_redis("#{runner.runner_info_key}:contacted_at", nil) stub_redis_runner_contacted_at(nil)
end end
context 'never contacted' do context 'never contacted' do
...@@ -128,7 +128,7 @@ describe Ci::Runner do ...@@ -128,7 +128,7 @@ describe Ci::Runner do
context 'with cache value' do context 'with cache value' do
context 'contacted long time ago time' do context 'contacted long time ago time' do
before do before do
stub_redis("#{runner.runner_info_key}:contacted_at", 1.year.ago.to_s) stub_redis_runner_contacted_at(1.year.ago.to_s)
end end
it { is_expected.to be_falsey } it { is_expected.to be_falsey }
...@@ -136,17 +136,17 @@ describe Ci::Runner do ...@@ -136,17 +136,17 @@ describe Ci::Runner do
context 'contacted 1s ago' do context 'contacted 1s ago' do
before do before do
stub_redis("#{runner.runner_info_key}:contacted_at", 1.second.ago.to_s) stub_redis_runner_contacted_at(1.second.ago.to_s)
end end
it { is_expected.to be_truthy } it { is_expected.to be_truthy }
end end
end end
def stub_redis(key, value) def stub_redis_runner_contacted_at(value)
redis = double redis = double
allow(Gitlab::Redis::SharedState).to receive(:with).and_yield(redis) allow(Gitlab::Redis::SharedState).to receive(:with).and_yield(redis)
allow(redis).to receive(:get).with(key).and_return(value) allow(redis).to receive(:get).with("#{runner.send(:runner_info_redis_cache_key)}:contacted_at").and_return(value)
end end
end end
...@@ -391,6 +391,48 @@ describe Ci::Runner do ...@@ -391,6 +391,48 @@ describe Ci::Runner do
end end
end end
describe '#update_runner_info' do
let(:runner) { create(:ci_runner) }
subject { runner.update_runner_info(contacted_at: Time.now) }
context 'when database was updated recently' do
before do
runner.update(contacted_at: Time.now)
end
it 'updates cache' do
expect_redis_update
subject
end
end
context 'when database was not updated recently' do
before do
runner.update(contacted_at: 2.hours.ago)
end
it 'updates database' do
expect_redis_update
expect { subject }.to change { runner.reload.contacted_at }
end
it 'updates cache' do
expect_redis_update
subject
end
end
def expect_redis_update
redis = double
expect(Gitlab::Redis::SharedState).to receive(:with).and_yield(redis)
expect(redis).to receive(:set).with("#{runner.send(:runner_info_redis_cache_key)}:contacted_at", anything)
end
end
describe '#destroy' do describe '#destroy' do
let(:runner) { create(:ci_runner) } let(:runner) { create(:ci_runner) }
......
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