From 603e93a4a3e5eba332dd6d2fed5f46ed8c3ffea6 Mon Sep 17 00:00:00 2001 From: David Kim <dkim@gitlab.com> Date: Wed, 8 May 2024 14:39:39 +1000 Subject: [PATCH] Reduce N+1 queries when publishing draft notes Use noteable instead to avoid reloading it multiple times --- app/models/draft_note.rb | 2 +- app/services/notes/build_service.rb | 6 +++++- spec/services/draft_notes/publish_service_spec.rb | 13 ++++++------- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/app/models/draft_note.rb b/app/models/draft_note.rb index b2848bf2cff2f..6f5c7436f06e5 100644 --- a/app/models/draft_note.rb +++ b/app/models/draft_note.rb @@ -5,7 +5,7 @@ class DraftNote < ApplicationRecord include Sortable include ShaAttribute - PUBLISH_ATTRS = %i[noteable_id noteable_type type note internal].freeze + PUBLISH_ATTRS = %i[noteable type note internal].freeze DIFF_ATTRS = %i[position original_position change_position commit_id].freeze sha_attribute :commit_id diff --git a/app/services/notes/build_service.rb b/app/services/notes/build_service.rb index 91993700e255b..96df14aa5746b 100644 --- a/app/services/notes/build_service.rb +++ b/app/services/notes/build_service.rb @@ -20,7 +20,11 @@ def execute discussion = discussion.convert_to_discussion! if discussion.can_convert_to_discussion? - params.merge!(discussion.reply_attributes) + reply_attributes = discussion.reply_attributes + # NOTE: Avoid overriding noteable if it already exists so that we don't have to reload noteable. + reply_attributes = reply_attributes.except(:noteable_id, :noteable_type) if params[:noteable] + + params.merge!(reply_attributes) end # The `confidential` param for notes is deprecated with 15.3 diff --git a/spec/services/draft_notes/publish_service_spec.rb b/spec/services/draft_notes/publish_service_spec.rb index ba4c579d391df..3822752b90ba6 100644 --- a/spec/services/draft_notes/publish_service_spec.rb +++ b/spec/services/draft_notes/publish_service_spec.rb @@ -224,19 +224,17 @@ def publish(draft: nil) end end - context 'with many draft notes', :use_sql_query_cache do + context 'with many draft notes', :use_sql_query_cache, :request_store do let(:merge_request) { create(:merge_request) } it 'reduce N+1 queries' do - create(:draft_note_on_text_diff, merge_request: merge_request, author: user, note: 'note 1') - create(:draft_note_on_text_diff, merge_request: merge_request, author: user, note: 'note 2') - create(:draft_note_on_text_diff, merge_request: merge_request, author: user, note: 'note 3') - create(:draft_note_on_text_diff, merge_request: merge_request, author: user, note: 'note 4') - create(:draft_note_on_text_diff, merge_request: merge_request, author: user, note: 'note 5') + 5.times do + create(:draft_note_on_discussion, merge_request: merge_request, author: user, note: 'some note') + end recorder = ActiveRecord::QueryRecorder.new(skip_cached: false) { publish } - expect(recorder.count).not_to be > 186 + expect(recorder.count).not_to be > 105 end end @@ -303,6 +301,7 @@ def update_file(file_path, new_content) refresh = MergeRequests::RefreshService.new(project: project, current_user: user) refresh.execute(oldrev, newrev, merge_request.source_branch_ref) + merge_request.reload expect { publish(draft: draft) }.to change { Suggestion.count }.by(1) .and change { DiffNote.count }.from(0).to(1) -- GitLab