Commit 6d74e474 authored by Rémy Coutable's avatar Rémy Coutable

Merge branch 'update-runner-information' into 'master'

Update runner version only when updating contacted_at

## What does this MR do?

Improves how we update runners table, especially the version.

This is another round of improvements to reduce number of `ci_runners` updates.

I did make `contacted_at` to be updated more often (on average every 15 minutes).
We will also update version information in one go to solve: https://gitlab.com/gitlab-org/gitlab-ce/issues/22206

Improves: https://gitlab.com/gitlab-org/gitlab-ce/issues/22590
Solves: https://gitlab.com/gitlab-org/gitlab-ce/issues/22206

See merge request !6537
parents 4dc61dc7 aa1ab8aa
Please view this file on the master branch, on stable branches it's out of date. Please view this file on the master branch, on stable branches it's out of date.
v 8.13.0 (unreleased) v 8.13.0 (unreleased)
- Update runner version only when updating contacted_at
- Add link from system note to compare with previous version - Add link from system note to compare with previous version
- Use gitlab-shell v3.6.2 (GIT TRACE logging) - Use gitlab-shell v3.6.2 (GIT TRACE logging)
- Fix centering of custom header logos (Ashley Dumaine) - Fix centering of custom header logos (Ashley Dumaine)
......
...@@ -2,7 +2,7 @@ module Ci ...@@ -2,7 +2,7 @@ module Ci
class Runner < ActiveRecord::Base class Runner < ActiveRecord::Base
extend Ci::Model extend Ci::Model
LAST_CONTACT_TIME = 2.hours.ago LAST_CONTACT_TIME = 1.hour.ago
AVAILABLE_SCOPES = %w[specific shared active paused online] AVAILABLE_SCOPES = %w[specific shared active paused online]
FORM_EDITABLE = %i[description tag_list active run_untagged locked] FORM_EDITABLE = %i[description tag_list active run_untagged locked]
......
...@@ -12,10 +12,9 @@ module Ci ...@@ -12,10 +12,9 @@ module Ci
# POST /builds/register # POST /builds/register
post "register" do post "register" do
authenticate_runner! authenticate_runner!
update_runner_last_contact(save: false)
update_runner_info
required_attributes! [:token] required_attributes! [:token]
not_found! unless current_runner.active? not_found! unless current_runner.active?
update_runner_info
build = Ci::RegisterBuildService.new.execute(current_runner) build = Ci::RegisterBuildService.new.execute(current_runner)
...@@ -41,10 +40,11 @@ module Ci ...@@ -41,10 +40,11 @@ module Ci
# PUT /builds/:id # PUT /builds/:id
put ":id" do put ":id" do
authenticate_runner! authenticate_runner!
update_runner_last_contact
build = Ci::Build.where(runner_id: current_runner.id).running.find(params[:id]) build = Ci::Build.where(runner_id: current_runner.id).running.find(params[:id])
forbidden!('Build has been erased!') if build.erased? forbidden!('Build has been erased!') if build.erased?
update_runner_info
build.update_attributes(trace: params[:trace]) if params[:trace] build.update_attributes(trace: params[:trace]) if params[:trace]
Gitlab::Metrics.add_event(:update_build, Gitlab::Metrics.add_event(:update_build,
......
...@@ -3,7 +3,7 @@ module Ci ...@@ -3,7 +3,7 @@ module Ci
module Helpers module Helpers
BUILD_TOKEN_HEADER = "HTTP_BUILD_TOKEN" BUILD_TOKEN_HEADER = "HTTP_BUILD_TOKEN"
BUILD_TOKEN_PARAM = :token BUILD_TOKEN_PARAM = :token
UPDATE_RUNNER_EVERY = 40 * 60 UPDATE_RUNNER_EVERY = 10 * 60
def authenticate_runners! def authenticate_runners!
forbidden! unless runner_registration_token_valid? forbidden! unless runner_registration_token_valid?
...@@ -30,14 +30,22 @@ module Ci ...@@ -30,14 +30,22 @@ module Ci
token && (build.valid_token?(token) || build.project.valid_runners_token?(token)) token && (build.valid_token?(token) || build.project.valid_runners_token?(token))
end end
def update_runner_last_contact(save: true) def update_runner_info
# Use a random threshold to prevent beating DB updates return unless update_runner?
# it generates a distribution between: [40m, 80m]
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 random threshold to prevent beating DB updates.
# It generates a distribution between [40m, 80m].
#
contacted_at_max_age = UPDATE_RUNNER_EVERY + Random.rand(UPDATE_RUNNER_EVERY) contacted_at_max_age = UPDATE_RUNNER_EVERY + Random.rand(UPDATE_RUNNER_EVERY)
if current_runner.contacted_at.nil? || Time.now - current_runner.contacted_at >= contacted_at_max_age
current_runner.contacted_at = Time.now current_runner.contacted_at.nil? ||
current_runner.save if current_runner.changed? && save (Time.now - current_runner.contacted_at) >= contacted_at_max_age
end
end end
def build_not_found! def build_not_found!
...@@ -57,11 +65,6 @@ module Ci ...@@ -57,11 +65,6 @@ module Ci
attributes_for_keys(["name", "version", "revision", "platform", "architecture"], params["info"]) attributes_for_keys(["name", "version", "revision", "platform", "architecture"], params["info"])
end end
def update_runner_info
current_runner.assign_attributes(get_runner_version_from_params)
current_runner.save if current_runner.changed?
end
def max_artifacts_size def max_artifacts_size
current_application_settings.max_artifacts_size.megabytes.to_i current_application_settings.max_artifacts_size.megabytes.to_i
end end
......
...@@ -35,18 +35,24 @@ describe Ci::API::API do ...@@ -35,18 +35,24 @@ describe Ci::API::API do
end end
end end
it "starts a build" do context 'when there is a pending build' do
register_builds info: { platform: :darwin } it 'starts a build' do
register_builds info: { platform: :darwin }
expect(response).to have_http_status(201)
expect(json_response['sha']).to eq(build.sha) expect(response).to have_http_status(201)
expect(runner.reload.platform).to eq("darwin") expect(json_response['sha']).to eq(build.sha)
expect(json_response["options"]).to eq({ "image" => "ruby:2.1", "services" => ["postgres"] }) expect(runner.reload.platform).to eq("darwin")
expect(json_response["variables"]).to include( expect(json_response["options"]).to eq({ "image" => "ruby:2.1", "services" => ["postgres"] })
{ "key" => "CI_BUILD_NAME", "value" => "spinach", "public" => true }, expect(json_response["variables"]).to include(
{ "key" => "CI_BUILD_STAGE", "value" => "test", "public" => true }, { "key" => "CI_BUILD_NAME", "value" => "spinach", "public" => true },
{ "key" => "DB_NAME", "value" => "postgres", "public" => true } { "key" => "CI_BUILD_STAGE", "value" => "test", "public" => true },
) { "key" => "DB_NAME", "value" => "postgres", "public" => true }
)
end
it 'updates runner info' do
expect { register_builds }.to change { runner.reload.contacted_at }
end
end end
context 'when builds are finished' do context 'when builds are finished' do
...@@ -159,13 +165,18 @@ describe Ci::API::API do ...@@ -159,13 +165,18 @@ describe Ci::API::API do
end end
context 'when runner is paused' do context 'when runner is paused' do
let(:inactive_runner) { create(:ci_runner, :inactive, token: "InactiveRunner") } let(:runner) { create(:ci_runner, :inactive, token: 'InactiveRunner') }
before do it 'responds with 404' do
register_builds inactive_runner.token register_builds
expect(response).to have_http_status 404
end end
it { expect(response).to have_http_status 404 } it 'does not update runner info' do
expect { register_builds }
.not_to change { runner.reload.contacted_at }
end
end end
def register_builds(token = runner.token, **params) def register_builds(token = runner.token, **params)
......
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