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 ...@@ -11,6 +11,10 @@ module MergeRequests
end end
def execute(merge_request) 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 # We don't allow change of source/target projects and source branch
# after merge request was created # after merge request was created
params.delete(:source_project_id) params.delete(:source_project_id)
...@@ -268,6 +272,32 @@ module MergeRequests ...@@ -268,6 +272,32 @@ module MergeRequests
def quick_action_options def quick_action_options
{ merge_request_diff_head_sha: params.delete(:merge_request_diff_head_sha) } { merge_request_diff_head_sha: params.delete(:merge_request_diff_head_sha) }
end 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
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 ...@@ -7,6 +7,10 @@ module EE
override :execute override :execute
def execute(merge_request) 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? unless update_task_event?
old_approvers = merge_request.overall_approvers(exclude_code_owners: true) old_approvers = merge_request.overall_approvers(exclude_code_owners: true)
end end
......
...@@ -943,6 +943,18 @@ RSpec.describe MergeRequests::UpdateService, :mailer do ...@@ -943,6 +943,18 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
end end
context 'updating asssignee_ids' do 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 it 'does not update assignee when assignee_id is invalid' do
merge_request.update!(assignee_ids: [user.id]) 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