diff --git a/app/models/ci/runner_manager.rb b/app/models/ci/runner_manager.rb index b9db19b9a1fc357df64b68b91644158fe64a72ae..aa470aa0d7abf5467888a77593fb8ab54a8fc92d 100644 --- a/app/models/ci/runner_manager.rb +++ b/app/models/ci/runner_manager.rb @@ -184,6 +184,15 @@ def heartbeat(values) end end + # While using update_columns may be useful from performance perspective, we still want + # the `updated_at` column to be updated. As most updates to the Ci::RunnerManager entity + # happen through the heartbeat model, when receiving some new/updated details from the + # runner side and without this change, `updated_at` may equal to `created_at` even months + # later, while the record did get multiple changes in that time. + def update_columns(attrs = {}) + super(attrs.reverse_merge(updated_at: Time.current)) + end + def supports_after_script_on_cancel? !!runtime_features['cancel_gracefully'] end diff --git a/spec/models/ci/runner_manager_spec.rb b/spec/models/ci/runner_manager_spec.rb index 0235ff0005853fcdb94cf4598057656d3849bff3..58d3b7fa173c6167bc27b6a50cef0bcbc10d62f8 100644 --- a/spec/models/ci/runner_manager_spec.rb +++ b/spec/models/ci/runner_manager_spec.rb @@ -514,7 +514,7 @@ end describe '#heartbeat', :freeze_time do - let(:runner_manager) { create(:ci_runner_machine, version: '15.0.0') } + let(:runner_manager) { create(:ci_runner_machine, version: '15.0.0', updated_at: (Time.current - 1.day)) } let(:executor) { 'shell' } let(:values) do { @@ -658,6 +658,7 @@ expect_redis_update expect { heartbeat }.to change { runner_manager.reload.read_attribute(:labels) } .from({}).to({ 'environment' => 'production', 'team' => 'backend' }) + .and change { runner_manager.reload.read_attribute(:updated_at) } end end end @@ -666,7 +667,7 @@ let(:version) { runner_manager.version } it 'does not schedule ci_runner_versions update' do - heartbeat + expect { heartbeat }.to change { runner_manager.reload.read_attribute(:updated_at) } expect(Ci::Runners::ProcessRunnerVersionUpdateWorker).not_to have_received(:perform_async) end @@ -678,7 +679,7 @@ it 'updates with expected executor type' do expect_redis_update - heartbeat + expect { heartbeat }.to change { runner_manager.reload.read_attribute(:updated_at) } expect(runner_manager.reload.read_attribute(:executor_type)).to eq(expected_executor_type) end @@ -695,7 +696,7 @@ def expected_executor_type it 'updates with unknown executor type' do expect_redis_update - heartbeat + expect { heartbeat }.to change { runner_manager.reload.read_attribute(:updated_at) } expect(runner_manager.reload.read_attribute(:executor_type)).to eq('unknown') end @@ -709,7 +710,7 @@ def expected_executor_type it 'updates labels' do expect_redis_update - heartbeat + expect { heartbeat }.to change { runner_manager.reload.read_attribute(:updated_at) } expect(runner_manager.reload.read_attribute(:labels)).to eq(values[:labels]) end @@ -732,6 +733,7 @@ def does_db_update .and change { runner_manager.reload.read_attribute(:config) } .and change { runner_manager.reload.read_attribute(:executor_type) } .and change { runner_manager.reload.read_attribute(:runtime_features) } + .and change { runner_manager.reload.read_attribute(:updated_at) } end end