From e8d2c2579383897a1dd7f9debd359abe8ae8373d Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Tue, 20 Jul 2021 09:55:51 +0000 Subject: Add latest changes from gitlab-org/gitlab@14-1-stable-ee --- app/services/ci/queue/builds_table_strategy.rb | 67 ++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 app/services/ci/queue/builds_table_strategy.rb (limited to 'app/services/ci/queue/builds_table_strategy.rb') diff --git a/app/services/ci/queue/builds_table_strategy.rb b/app/services/ci/queue/builds_table_strategy.rb new file mode 100644 index 00000000000..c941734ac40 --- /dev/null +++ b/app/services/ci/queue/builds_table_strategy.rb @@ -0,0 +1,67 @@ +# frozen_string_literal: true + +module Ci + module Queue + class BuildsTableStrategy + attr_reader :runner + + def initialize(runner) + @runner = runner + end + + # rubocop:disable CodeReuse/ActiveRecord + def builds_for_shared_runner + relation = new_builds + # don't run projects which have not enabled shared runners and builds + .joins('INNER JOIN projects ON ci_builds.project_id = projects.id') + .where(projects: { shared_runners_enabled: true, pending_delete: false }) + .joins('LEFT JOIN project_features ON ci_builds.project_id = project_features.project_id') + .where('project_features.builds_access_level IS NULL or project_features.builds_access_level > 0') + + if Feature.enabled?(:ci_queueing_disaster_recovery_disable_fair_scheduling, runner, type: :ops, default_enabled: :yaml) + # if disaster recovery is enabled, we fallback to FIFO scheduling + relation.order('ci_builds.id ASC') + else + # 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 + relation + .joins("LEFT JOIN (#{running_builds_for_shared_runners.to_sql}) AS project_builds ON ci_builds.project_id = project_builds.project_id") + .order(Arel.sql('COALESCE(project_builds.running_builds, 0) ASC'), 'ci_builds.id ASC') + end + end + + def builds_matching_tag_ids(relation, ids) + # pick builds that does not have other tags than runner's one + relation.matches_tag_ids(ids) + end + + def builds_with_any_tags(relation) + # pick builds that have at least one tag + relation.with_any_tags + end + + def order(relation) + relation.order('id ASC') + end + + def new_builds + ::Ci::Build.pending.unstarted + end + + def build_ids(relation) + relation.pluck(:id) + end + + private + + def running_builds_for_shared_runners + ::Ci::Build.running + .where(runner: ::Ci::Runner.instance_type) + .group(:project_id) + .select(:project_id, 'COUNT(*) AS running_builds') + end + # rubocop:enable CodeReuse/ActiveRecord + end + end +end -- cgit v1.2.1