Commit 04122f32 authored by Kerri Miller's avatar Kerri Miller

Use specialized services for faster updates

When we're only updating a single attribute of a merge request, it can
be MUCH faster to use a specialized update service for that specific
attribute (or relationship) than the "update the world" approach of
MergeRequests::UpdateService#execute does by default.
parent 2c9ac85a
......@@ -11,6 +11,10 @@ module MergeRequests
end
def execute(merge_request)
updated_merge_request = update_merge_request_with_specialized_service(merge_request)
return updated_merge_request unless updated_merge_request.nil?
# We don't allow change of source/target projects and source branch
# after merge request was created
params.delete(:source_project_id)
......@@ -268,6 +272,32 @@ module MergeRequests
def quick_action_options
{ merge_request_diff_head_sha: params.delete(:merge_request_diff_head_sha) }
end
def update_merge_request_with_specialized_service(merge_request)
return unless params.delete(:use_specialized_service)
# If we're attempting to modify only a single attribute, look up whether
# we have a specialized, targeted service we should use instead. We may
# in the future extend this to include specialized services that operate
# on multiple attributes, but for now limit to only single attribute
# updates.
#
return unless params.keys.length == 1
updated_merge_request = nil
case params.keys[0].to_sym
when :assignee_ids
updated_merge_request = assignees_service.execute(merge_request)
end
updated_merge_request
end
def assignees_service
@assignees_service ||= ::MergeRequests::UpdateAssigneesService
.new(project, current_user, params)
end
end
end
......
---
title: Add framework for using specialized services to improve performance of MergeRequests::UpdateService
merge_request: 58836
author:
type: performance
......@@ -7,6 +7,10 @@ module EE
override :execute
def execute(merge_request)
updated_merge_request = update_merge_request_with_specialized_service(merge_request)
return updated_merge_request unless updated_merge_request.nil?
unless update_task_event?
old_approvers = merge_request.overall_approvers(exclude_code_owners: true)
end
......
......@@ -943,6 +943,18 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
end
context 'updating asssignee_ids' do
context 'when :use_specialized_service is true' do
it 'passes the update action to ::MergeRequests::UpdateAssigneesService' do
expect(::MergeRequests::UpdateAssigneesService)
.to receive(:new).and_call_original
update_merge_request({
assignee_ids: [user2.id],
use_specialized_service: true
})
end
end
it 'does not update assignee when assignee_id is invalid' do
merge_request.update!(assignee_ids: [user.id])
......
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