Commit c59b4b94 authored by Alex Kalderimis's avatar Alex Kalderimis

Move issue placement to its own worker

This adds an issue_placement_worker that places recently created
unpositioned issues either at the end or the start of the issue set.
parent 5c953a59
# frozen_string_literal: true
class IssuePlacementWorker
include ApplicationWorker
idempotent!
feature_category :issue_tracking
urgency :high
worker_resource_boundary :cpu
weight 2
# rubocop: disable CodeReuse/ActiveRecord
def perform(issue_id, placement = :end)
issue = Issue.find(issue_id)
to_place = Issue
.relative_positioning_query_base(issue)
.where(Issue.arel_table[:created_at].gteq(issue.created_at - 5.minutes))
.order_created_at_desc
if placement == :end
Issue.move_nulls_to_end(to_place.to_a.reverse)
elsif placement == :start
Issue.move_nulls_to_start(to_place.to_a)
end
rescue ActiveRecord::RecordNotFound, RelativePositioning::NoSpaceLeft => e
Gitlab::ErrorTracking.log_exception(e, issue_id: issue_id, placement: placement)
IssueRebalancingWorker.perform_async(nil, issue.project_id) if issue && e.is_a?(RelativePositioning::NoSpaceLeft)
end
# rubocop: enable CodeReuse/ActiveRecord
end
......@@ -12,10 +12,10 @@ class NewIssueWorker # rubocop:disable Scalability/IdempotentWorker
def perform(issue_id, user_id)
return unless objects_found?(issue_id, user_id)
::Issues::ReorderService.new(nil, user, placement: :end).execute(issuable)
::EventCreateService.new.open_issue(issuable, user)
::NotificationService.new.new_issue(issuable, user)
issuable.create_cross_references!(user)
IssuePlacementWorker.perform_async(issue_id, :end)
end
def issuable_class
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe IssuePlacementWorker do
describe '#perform' do
let_it_be(:project) { create_default(:project) }
let_it_be(:issue) { create(:issue, relative_position: nil) }
let_it_be(:issue_a) { create(:issue, relative_position: nil, created_at: issue.created_at - 1.minute) }
let_it_be(:issue_b) { create(:issue, relative_position: nil, created_at: issue.created_at - 6.minutes) }
let_it_be(:issue_c) { create(:issue, relative_position: nil, created_at: issue.created_at + 1.minute) }
let_it_be(:issue_d) { create(:issue, relative_position: nil, created_at: issue.created_at + 6.minutes) }
let_it_be(:issue_e) { create(:issue, relative_position: 10, created_at: issue.created_at + 3.minutes) }
let_it_be(:irrelevant) { create(:issue, project: create(:project), created_at: issue.created_at - 30.seconds) }
it 'places all issues created at most 5 minutes before this one at the end, most recent last' do
described_class.new.perform(issue.id, :end)
expect(project.issues.order_relative_position_asc)
.to eq([issue_e, issue_a, issue, issue_c, issue_d, issue_b])
end
it 'places all issues created at most 5 minutes before this one at the start, most recent first' do
described_class.new.perform(issue.id, :start)
expect(project.issues.order_relative_position_asc)
.to eq([issue_d, issue_c, issue, issue_a, issue_e, issue_b])
end
it 'anticipates the failure to find the issue' do
id = non_existing_record_id
expect(Gitlab::ErrorTracking)
.to receive(:log_exception)
.with(ActiveRecord::RecordNotFound, issue_id: id, placement: :end)
described_class.new.perform(id, :end)
end
it 'anticipates the failure to place the issues, and schedules rebalancing' do
allow(Issue).to receive(:move_nulls_to_end) { raise RelativePositioning::NoSpaceLeft }
expect(IssueRebalancingWorker).to receive(:perform_async).with(nil, project.id)
expect(Gitlab::ErrorTracking)
.to receive(:log_exception)
.with(RelativePositioning::NoSpaceLeft, issue_id: issue.id, placement: :end)
described_class.new.perform(issue.id, :end)
end
end
end
......@@ -49,10 +49,9 @@ RSpec.describe NewIssueWorker do
end
it 'moves the issue to the end' do
other_issue = create(:issue, project: project, relative_position: 100)
expect(IssuePlacementWorker).to receive(:perform_async).with(issue.id, :end)
expect { worker.perform(issue.id, user.id) }
.to change { issue.reset.relative_position }.to(be > other_issue.relative_position)
worker.perform(issue.id, user.id)
end
it 'creates a notification for the mentioned user' do
......
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