diff --git a/app/controllers/api/v1/jobs_controller.rb b/app/controllers/api/v1/jobs_controller.rb index a40714285..2af2eedbf 100644 --- a/app/controllers/api/v1/jobs_controller.rb +++ b/app/controllers/api/v1/jobs_controller.rb @@ -7,24 +7,20 @@ class Api::V1::JobsController < Api::V1::BaseController before_filter :authenticate_user! def shift - - @build_list = BuildList.next_build if current_user.system? + @build_list = BuildList.next_build(arch_ids, platform_ids) if current_user.system? if @build_list set_builder else - platform_ids = Platform.where(name: params[:platforms].split(',')).pluck(:id) if params[:platforms].present? - arch_ids = Arch.where(name: params[:arches].split(',')).pluck(:id) if params[:arches].present? build_lists = BuildList.scoped_to_arch(arch_ids). for_status([BuildList::BUILD_PENDING, BuildList::RERUN_TESTS]). - scoped_to_arch(arch_ids). + for_platform(platform_ids). oldest.order(:created_at) - build_lists = build_lists.for_platform(platform_ids) if platform_ids.present? ActiveRecord::Base.transaction do if current_user.system? @build_list ||= build_lists.external_nodes(:everything).first else - @build_list = build_lists.external_nodes(:owned).for_user(current_user).first + @build_list = build_lists.external_nodes(:owned).for_user(current_user).first @build_list ||= build_lists.external_nodes(:everything). accessible_by(current_ability, :everything).readonly(false).first end @@ -85,6 +81,20 @@ class Api::V1::JobsController < Api::V1::BaseController protected + def platform_ids + @platform_ids ||= begin + platforms = params[:platforms].to_s.split(',') + platforms.present? ? Platform.where(name: platforms).pluck(:id) : [] + end + end + + def arch_ids + @arch_ids ||= begin + arches = params[:arches].to_s.split(',') + arches.present? ? Arch.where(name: arches).pluck(:id) : [] + end + end + def set_builder return unless @build_list @build_list.builder = current_user diff --git a/app/models/build_list.rb b/app/models/build_list.rb index 3d66f7c2a..0e29c1e8e 100644 --- a/app/models/build_list.rb +++ b/app/models/build_list.rb @@ -125,15 +125,15 @@ class BuildList < ActiveRecord::Base scope :for_status, ->(status) { where(status: status) if status.present? } scope :for_user, ->(user) { where(user_id: user.id) } scope :not_owned_external_nodes, -> { where("#{table_name}.external_nodes is null OR #{table_name}.external_nodes != ?", :owned) } - scope :external_nodes, ->(type) { where("#{table_name}.external_nodes = ?", type) } - scope :oldest, -> { where("#{table_name}.updated_at < ?", Time.zone.now - 15.seconds) } - scope :for_platform, ->(platform) { where(build_for_platform_id: platform) } - scope :by_mass_build, ->(mass_build) { where(mass_build_id: mass_build) } - scope :scoped_to_arch, ->(arch) { where(arch_id: arch) if arch.present? } - scope :scoped_to_save_platform, ->(pl_id) { where(save_to_platform_id: pl_id) if pl_id.present? } - scope :scoped_to_project_version, ->(pr_version) { where(project_version: pr_version) if pr_version.present? } - scope :scoped_to_is_circle, ->(is_circle) { where(is_circle: is_circle) } - scope :for_creation_date_period, ->(start_date, end_date) { + scope :external_nodes, ->(type) { where("#{table_name}.external_nodes = ?", type) } + scope :oldest, -> { where("#{table_name}.updated_at < ?", Time.zone.now - 15.seconds) } + scope :for_platform, ->(platform) { where(build_for_platform_id: platform) if platform.present? } + scope :by_mass_build, ->(mass_build) { where(mass_build_id: mass_build) } + scope :scoped_to_arch, ->(arch) { where(arch_id: arch) if arch.present? } + scope :scoped_to_save_platform, ->(pl_id) { where(save_to_platform_id: pl_id) if pl_id.present? } + scope :scoped_to_project_version, ->(pr_version) { where(project_version: pr_version) if pr_version.present? } + scope :scoped_to_is_circle, ->(is_circle) { where(is_circle: is_circle) } + scope :for_creation_date_period, ->(start_date, end_date) { s = all s = s.where(["#{table_name}.created_at >= ?", start_date]) if start_date s = s.where(["#{table_name}.created_at <= ?", end_date]) if end_date @@ -587,23 +587,37 @@ class BuildList < ActiveRecord::Base ) end - def self.next_build - kind_id = Redis.current.spop(USER_BUILDS_SET) - key = "user_build_#{kind_id}_rpm_worker_default" if kind_id - task = Resque.pop(key) if key - Redis.current.sadd(USER_BUILDS_SET, kind_id) if task + def self.next_build(arch_ids, platform_ids) + kind_id = Redis.current.spop(USER_BUILDS_SET) + key = "user_build_#{kind_id}_rpm_worker_default" if kind_id + build_list = next_build_from_queue(kind_id, key, arch_ids, platform_ids) if key + Redis.current.sadd(USER_BUILDS_SET, kind_id) if build_list + kind_id ||= Redis.current.spop(MASS_BUILDS_SET) + key ||= "mass_build_#{kind_id}_rpm_worker" if kind_id + build_list ||= next_build_from_queue(kind_id, key, arch_ids, platform_ids, true) if key + Redis.current.sadd(MASS_BUILDS_SET, kind_id) if build_list && key =~ /^mass_build/ - kind_id ||= Redis.current.spop(MASS_BUILDS_SET) - key ||= "mass_build_#{kind_id}_rpm_worker" if kind_id - task ||= Resque.pop(key) if key - Redis.current.sadd(MASS_BUILDS_SET, kind_id) if task && key =~ /^mass_build/ + build_list.delayed_add_job_to_abf_worker_queue if build_list.present? + build_list + end - if task - build_list = BuildList.where(id: task['args'][0]['id']).first - build_list.delayed_add_job_to_abf_worker_queue if build_list.present? - build_list + def self.next_build_from_queue(kind_id, key, arch_ids, platform_ids, mass_build = false) + if kind_id && (arch_ids.present? || platform_ids.present?) + build_list = BuildList.where(user_id: kind_id). + scoped_to_arch(arch_ids). + for_status([BuildList::BUILD_PENDING, BuildList::RERUN_TESTS]). + for_platform(platform_ids) + build_list = build_list.where.not(mass_build_id: nil) if mass_build + build_list = build_list.oldest.order(:created_at).first + + build_list = nil if build_list && build_list.destroy_from_resque_queue != 1 + elsif key + task = Resque.pop(key) end + + build_list ||= BuildList.where(id: task['args'][0]['id']).first if task + build_list end def delayed_add_job_to_abf_worker_queue(*args) diff --git a/spec/controllers/api/v1/issues_controller_spec.rb b/spec/controllers/api/v1/issues_controller_spec.rb index 60f2924d8..ec2b5cd05 100644 --- a/spec/controllers/api/v1/issues_controller_spec.rb +++ b/spec/controllers/api/v1/issues_controller_spec.rb @@ -140,12 +140,12 @@ describe Api::V1::IssuesController do it 'can assignee issue in own project' do post :create, @create_params.deep_merge(project_id: @own_hidden_project.id, issue: {assignee_id: @issue.user.id}) - @own_hidden_project.issues.reload.last.assignee.id.should == @issue.user.id + @own_hidden_project.issues.order(:id).last.assignee.id.should == @issue.user.id end it "can't assignee issue in open project" do post :create, @create_params.deep_merge(project_id: @open_project.id, issue: {assignee_id: @issue.user.id}) - @open_project.issues.reload.last.assignee.should be_nil + @open_project.issues.order(:id).last.assignee.should be_nil end end diff --git a/spec/models/build_list_spec.rb b/spec/models/build_list_spec.rb index b28cdc5df..6453f061f 100644 --- a/spec/models/build_list_spec.rb +++ b/spec/models/build_list_spec.rb @@ -15,6 +15,48 @@ describe BuildList do end end + context '#next_build' do + let!(:build_list) { FactoryGirl.create(:build_list, updated_at: Time.now - 20.seconds) } + + it 'returns build list' do + expect_any_instance_of(BuildList).to receive(:delayed_add_job_to_abf_worker_queue) + expect(BuildList.next_build([], [])).to eq build_list + end + + context 'filtering build lists by platform' do + it 'returns build list for correct platform' do + expect_any_instance_of(BuildList).to receive(:delayed_add_job_to_abf_worker_queue) + expect(BuildList.next_build([], [build_list.build_for_platform_id])).to eq build_list + end + + it 'returns nothing if build list does not in queue' do + expect_any_instance_of(BuildList).to receive(:destroy_from_resque_queue).and_return(0) + expect(BuildList.next_build([], [build_list.build_for_platform_id])).to be_nil + end + + it 'returns nothing for wrong platform' do + expect(BuildList.next_build([], [-1])).to be_nil + end + end + + context 'filtering build lists by arch' do + it 'returns build list for correct arch' do + expect_any_instance_of(BuildList).to receive(:delayed_add_job_to_abf_worker_queue) + expect(BuildList.next_build([build_list.arch_id], [])).to eq build_list + end + + it 'returns nothing if build list does not in queue' do + expect_any_instance_of(BuildList).to receive(:destroy_from_resque_queue).and_return(0) + expect(BuildList.next_build([build_list.arch_id], [])).to be_nil + end + + it 'returns nothing for wrong arch' do + expect(BuildList.next_build([-1], [])).to be_nil + end + end + + end + context "#notify_users" do let!(:user) { FactoryGirl.create(:user) } let!(:build_list) { FactoryGirl.create(:build_list,