summaryrefslogtreecommitdiff
path: root/app/services/ci/register_build_service.rb
diff options
context:
space:
mode:
Diffstat (limited to 'app/services/ci/register_build_service.rb')
-rw-r--r--app/services/ci/register_build_service.rb62
1 files changed, 43 insertions, 19 deletions
diff --git a/app/services/ci/register_build_service.rb b/app/services/ci/register_build_service.rb
index 74b5ebf372b..6f03bf2be13 100644
--- a/app/services/ci/register_build_service.rb
+++ b/app/services/ci/register_build_service.rb
@@ -2,48 +2,72 @@ module Ci
# This class responsible for assigning
# proper pending build to runner on runner API request
class RegisterBuildService
- def execute(current_runner)
- builds = Ci::Build.pending.unstarted
+ include Gitlab::CurrentSettings
+ attr_reader :runner
+
+ Result = Struct.new(:build, :valid?)
+
+ def initialize(runner)
+ @runner = runner
+ end
+
+ def execute
builds =
- if current_runner.shared?
- builds.
- # don't run projects which have not enabled shared runners and builds
- joins(:project).where(projects: { shared_runners_enabled: true }).
- joins('LEFT JOIN project_features ON ci_builds.gl_project_id = project_features.project_id').
-
- # this returns builds that are ordered by number of running builds
- # we prefer projects that don't use shared runners at all
- joins("LEFT JOIN (#{running_builds_for_shared_runners.to_sql}) AS project_builds ON ci_builds.gl_project_id=project_builds.gl_project_id").
- where('project_features.builds_access_level IS NULL or project_features.builds_access_level > 0').
- order('COALESCE(project_builds.running_builds, 0) ASC', 'ci_builds.id ASC')
+ if runner.shared?
+ builds_for_shared_runner
else
- # do run projects which are only assigned to this runner (FIFO)
- builds.where(project: current_runner.projects.with_builds_enabled).order('created_at ASC')
+ builds_for_specific_runner
end
build = builds.find do |build|
- current_runner.can_pick?(build)
+ runner.can_pick?(build)
end
if build
# In case when 2 runners try to assign the same build, second runner will be declined
# with StateMachines::InvalidTransition or StaleObjectError when doing run! or save method.
- build.runner_id = current_runner.id
+ build.runner_id = runner.id
build.run!
end
- build
+ Result.new(build, true)
rescue StateMachines::InvalidTransition, ActiveRecord::StaleObjectError
- nil
+ Result.new(build, false)
end
private
+ def builds_for_shared_runner
+ new_builds.
+ # don't run projects which have not enabled shared runners and builds
+ joins(:project).where(projects: { shared_runners_enabled: true }).
+ joins('LEFT JOIN project_features ON ci_builds.gl_project_id = project_features.project_id').
+ where('project_features.builds_access_level IS NULL or project_features.builds_access_level > 0').
+
+ # Implement fair scheduling
+ # this returns builds that are ordered by number of running builds
+ # we prefer projects that don't use shared runners at all
+ joins("LEFT JOIN (#{running_builds_for_shared_runners.to_sql}) AS project_builds ON ci_builds.gl_project_id=project_builds.gl_project_id").
+ order('COALESCE(project_builds.running_builds, 0) ASC', 'ci_builds.id ASC')
+ end
+
+ def builds_for_specific_runner
+ new_builds.where(project: runner.projects.with_builds_enabled).order('created_at ASC')
+ end
+
def running_builds_for_shared_runners
Ci::Build.running.where(runner: Ci::Runner.shared).
group(:gl_project_id).select(:gl_project_id, 'count(*) AS running_builds')
end
+
+ def new_builds
+ Ci::Build.pending.unstarted
+ end
+
+ def shared_runner_build_limits_feature_enabled?
+ ENV['DISABLE_SHARED_RUNNER_BUILD_MINUTES_LIMIT'].to_s != 'true'
+ end
end
end