summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/models/ci/build.rb2
-rw-r--r--app/services/ci/register_job_service.rb5
-rw-r--r--changelogs/unreleased/1340-request-job-with-age.yml5
-rw-r--r--db/migrate/20190516011213_add_build_queued_at_index.rb19
-rw-r--r--db/schema.rb3
-rw-r--r--lib/api/runner.rb1
-rw-r--r--spec/requests/api/runner_spec.rb24
7 files changed, 58 insertions, 1 deletions
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index 0a90995f689..1b67a7272bc 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -140,6 +140,8 @@ module Ci
where("EXISTS (?)", matcher)
end
+ scope :queued_before, ->(time) { where(arel_table[:queued_at].lt(time)) }
+
##
# TODO: Remove these mounters when we remove :ci_enable_legacy_artifacts feature flag
mount_uploader :legacy_artifacts_file, LegacyArtifactUploader, mount_on: :artifacts_file
diff --git a/app/services/ci/register_job_service.rb b/app/services/ci/register_job_service.rb
index 6707a1363d0..baa3f898b2d 100644
--- a/app/services/ci/register_job_service.rb
+++ b/app/services/ci/register_job_service.rb
@@ -36,6 +36,11 @@ module Ci
builds = builds.with_any_tags
end
+ # pick builds that older than specified age
+ if params.key?(:job_age)
+ builds = builds.queued_before(params[:job_age].seconds.ago)
+ end
+
builds.each do |build|
next unless runner.can_pick?(build)
diff --git a/changelogs/unreleased/1340-request-job-with-age.yml b/changelogs/unreleased/1340-request-job-with-age.yml
new file mode 100644
index 00000000000..766ac008c2e
--- /dev/null
+++ b/changelogs/unreleased/1340-request-job-with-age.yml
@@ -0,0 +1,5 @@
+---
+title: "Added option to filter jobs by age in the /job/request API endpoint."
+merge_request: 1340
+author: Dmitry Chepurovskiy
+type: added
diff --git a/db/migrate/20190516011213_add_build_queued_at_index.rb b/db/migrate/20190516011213_add_build_queued_at_index.rb
new file mode 100644
index 00000000000..77ffa7cd4e9
--- /dev/null
+++ b/db/migrate/20190516011213_add_build_queued_at_index.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+# This migration make queued_at field indexed to speed up builds filtering by job_age
+
+class AddBuildQueuedAtIndex < ActiveRecord::Migration[5.1]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :ci_builds, :queued_at
+ end
+
+ def down
+ remove_concurrent_index :ci_builds, :queued_at
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 9d367938cec..412b5313b69 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20190515125613) do
+ActiveRecord::Schema.define(version: 20190516011213) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -380,6 +380,7 @@ ActiveRecord::Schema.define(version: 20190515125613) do
t.index ["project_id", "id"], name: "index_ci_builds_on_project_id_and_id", using: :btree
t.index ["project_id", "status"], name: "index_ci_builds_project_id_and_status_for_live_jobs_partial2", where: "(((type)::text = 'Ci::Build'::text) AND ((status)::text = ANY (ARRAY[('running'::character varying)::text, ('pending'::character varying)::text, ('created'::character varying)::text])))", using: :btree
t.index ["protected"], name: "index_ci_builds_on_protected", using: :btree
+ t.index ["queued_at"], name: "index_ci_builds_on_queued_at", using: :btree
t.index ["runner_id"], name: "index_ci_builds_on_runner_id", using: :btree
t.index ["scheduled_at"], name: "partial_index_ci_builds_on_scheduled_at_with_scheduled_jobs", where: "((scheduled_at IS NOT NULL) AND ((type)::text = 'Ci::Build'::text) AND ((status)::text = 'scheduled'::text))", using: :btree
t.index ["stage_id", "stage_idx"], name: "tmp_build_stage_position_index", where: "(stage_idx IS NOT NULL)", using: :btree
diff --git a/lib/api/runner.rb b/lib/api/runner.rb
index ea36c24eca2..fdf4904e9f5 100644
--- a/lib/api/runner.rb
+++ b/lib/api/runner.rb
@@ -98,6 +98,7 @@ module API
optional :certificate, type: String, desc: %q(Session's certificate)
optional :authorization, type: String, desc: %q(Session's authorization)
end
+ optional :job_age, type: Integer, desc: %q(Job should be older than passed age in seconds to be ran on runner)
end
post '/request' do
authenticate_runner!
diff --git a/spec/requests/api/runner_spec.rb b/spec/requests/api/runner_spec.rb
index b331da1acba..4006e697a41 100644
--- a/spec/requests/api/runner_spec.rb
+++ b/spec/requests/api/runner_spec.rb
@@ -542,6 +542,30 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
end
end
+ context 'when job filtered by job_age' do
+ let!(:job) { create(:ci_build, :tag, pipeline: pipeline, name: 'spinach', stage: 'test', stage_idx: 0, queued_at: 60.seconds.ago) }
+
+ context 'job is queued less than job_age parameter' do
+ let(:job_age) { 120 }
+
+ it 'gives 204' do
+ request_job(job_age: job_age)
+
+ expect(response).to have_gitlab_http_status(204)
+ end
+ end
+
+ context 'job is queued more than job_age parameter' do
+ let(:job_age) { 30 }
+
+ it 'picks a job' do
+ request_job(job_age: job_age)
+
+ expect(response).to have_gitlab_http_status(201)
+ end
+ end
+ end
+
context 'when job is made for branch' do
it 'sets tag as ref_type' do
request_job