Optimize runner manager heartbeat to skip unnecessary database updates
What does this MR do and why?
Optimizes the Ci::RunnerManager#heartbeat method to prevent unnecessary database writes when runner attributes haven't changed.
Runners send frequent heartbeat requests, and previously every heartbeat would trigger a database update even when only contacted_at changed (which is tracked in Redis cache). This MR adds a changed? check before calling update_columns, reducing database load for large runner fleets with stable configurations.
Changes:
- Modified
app/models/ci/runner_manager.rb: Added&& changed?condition to skipupdate_columnswhen no attributes have changed - Added test coverage for no-change scenarios, cache-only updates, and partial attribute changes
References
- Issue: https://gitlab.com/gitlab-data/analytics/-/issues/25129+s
- Related: Runner heartbeat instructs postgres to UPDATE f... (#525577) • Unassigned • Next 4-6 releases
Screenshots or screen recordings
N/A - Backend optimization
How to set up and validate locally
- Run the new specs to verify the optimization:
bundle exec rspec spec/models/ci/runner_manager_spec.rb
- To observe the behavior in development:
# In rails console
runner = Ci::Runner.first
manager = runner.runner_managers.first
# Heartbeat with no changes - should not update DB
manager.heartbeat({ version: manager.version })
# Heartbeat with changes - should update DB
manager.heartbeat({ version: '16.0.0' })
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.
Edited by Pedro Pombeiro