summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaco Guzman <pacoguzmanp@gmail.com>2016-08-01 16:55:51 +0200
committerPaco Guzman <pacoguzmanp@gmail.com>2016-08-02 16:04:15 +0200
commit8716ff7f63fff0b056e110bef930c32a98e86c63 (patch)
tree0c00cc19b1cfff77eb1472840ed456e852fbfc49
parentaac8dcf12cdd5b102b220d9b2f5dded2d1362ffc (diff)
downloadgitlab-ce-8716ff7f63fff0b056e110bef930c32a98e86c63.tar.gz
Speedup DiffNote#active? on discussions, preloading noteables and avoid touching git repository to return diff_refs when possible
- Preloading noteable we share the same noteable instance when more than one discussion refers to the same noteable. - Any other call to that object that is cached in that object will be for any discussion. - In those cases where merge_request_diff has all the sha stored to build a diff_refs get that diff_refs using directly those sha instead accessing to the git repository to first get the commits and later the sha.
-rw-r--r--CHANGELOG1
-rw-r--r--app/controllers/projects/merge_requests_controller.rb2
-rw-r--r--app/helpers/notes_helper.rb4
-rw-r--r--app/models/diff_note.rb12
-rw-r--r--app/models/discussion.rb6
-rw-r--r--app/models/merge_request.rb15
-rw-r--r--app/models/merge_request_diff.rb4
-rw-r--r--spec/models/diff_note_spec.rb4
-rw-r--r--spec/models/merge_request_spec.rb24
9 files changed, 67 insertions, 5 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 42476248256..ece0a5c1e78 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -40,6 +40,7 @@ v 8.11.0 (unreleased)
- Multiple trigger variables show in separate lines (Katarzyna Kobierska Ula Budziszewska)
- Profile requests when a header is passed
- Avoid calculation of line_code and position for _line partial when showing diff notes on discussion tab.
+ - Speedup DiffNote#active? on discussions, preloading noteables and avoid touching git repository to return diff_refs when possible
- Add commit stats in commit api. !5517 (dixpac)
- Make error pages responsive (Takuya Noguchi)
- Change requests_profiles resource constraint to catch virtually any file
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index 03166294ddd..116e7904a4e 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -378,6 +378,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController
fresh.
discussions
+ preload_noteable_for_regular_notes(@discussions.flat_map(&:notes))
+
# This is not executed lazily
@notes = Banzai::NoteRenderer.render(
@discussions.flat_map(&:notes),
diff --git a/app/helpers/notes_helper.rb b/app/helpers/notes_helper.rb
index 0c47abe0fba..26bde2230a9 100644
--- a/app/helpers/notes_helper.rb
+++ b/app/helpers/notes_helper.rb
@@ -92,6 +92,10 @@ module NotesHelper
project.team.max_member_access_for_user_ids(user_ids)
end
+ def preload_noteable_for_regular_notes(notes)
+ ActiveRecord::Associations::Preloader.new.preload(notes.select { |note| !note.for_commit? }, :noteable)
+ end
+
def note_max_access_for_user(note)
note.project.team.human_max_access(note.author_id)
end
diff --git a/app/models/diff_note.rb b/app/models/diff_note.rb
index 9671955db36..c816deb4e0c 100644
--- a/app/models/diff_note.rb
+++ b/app/models/diff_note.rb
@@ -67,7 +67,7 @@ class DiffNote < Note
return false unless supported?
return true if for_commit?
- diff_refs ||= self.noteable.diff_refs
+ diff_refs ||= noteable_diff_refs
self.position.diff_refs == diff_refs
end
@@ -78,6 +78,14 @@ class DiffNote < Note
!self.for_merge_request? || self.noteable.support_new_diff_notes?
end
+ def noteable_diff_refs
+ if noteable.respond_to?(:diff_sha_refs)
+ noteable.diff_sha_refs
+ else
+ noteable.diff_refs
+ end
+ end
+
def set_original_position
self.original_position = self.position.dup
end
@@ -96,7 +104,7 @@ class DiffNote < Note
self.project,
nil,
old_diff_refs: self.position.diff_refs,
- new_diff_refs: self.noteable.diff_refs,
+ new_diff_refs: noteable_diff_refs,
paths: self.position.paths
).execute(self)
end
diff --git a/app/models/discussion.rb b/app/models/discussion.rb
index 74facfd1c9c..e2218a5f02b 100644
--- a/app/models/discussion.rb
+++ b/app/models/discussion.rb
@@ -49,6 +49,12 @@ class Discussion
self.noteable == target && !diff_discussion?
end
+ def active?
+ return @active if defined?(@active)
+
+ @active = first_note.active?
+ end
+
def expanded?
!diff_discussion? || active?
end
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index f1b9c1d6feb..a99c4ba52a4 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -255,6 +255,19 @@ class MergeRequest < ActiveRecord::Base
)
end
+ # Return diff_refs instance trying to not touch the git repository
+ def diff_sha_refs
+ if merge_request_diff && merge_request_diff.diff_refs_by_sha?
+ return Gitlab::Diff::DiffRefs.new(
+ base_sha: merge_request_diff.base_commit_sha,
+ start_sha: merge_request_diff.start_commit_sha,
+ head_sha: merge_request_diff.head_commit_sha
+ )
+ else
+ diff_refs
+ end
+ end
+
def validate_branches
if target_project == source_project && target_branch == source_branch
errors.add :branch_conflict, "You can not use same project/branch for source and target"
@@ -659,7 +672,7 @@ class MergeRequest < ActiveRecord::Base
end
def support_new_diff_notes?
- diff_refs && diff_refs.complete?
+ diff_sha_refs && diff_sha_refs.complete?
end
def update_diff_notes_positions(old_diff_refs:, new_diff_refs:)
diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb
index 3f520c8f3ff..119266f2d2c 100644
--- a/app/models/merge_request_diff.rb
+++ b/app/models/merge_request_diff.rb
@@ -82,6 +82,10 @@ class MergeRequestDiff < ActiveRecord::Base
project.commit(self.head_commit_sha)
end
+ def diff_refs_by_sha?
+ base_commit_sha? && head_commit_sha? && start_commit_sha?
+ end
+
def compare
@compare ||=
begin
diff --git a/spec/models/diff_note_spec.rb b/spec/models/diff_note_spec.rb
index af8e890ca95..1fa96eb1f15 100644
--- a/spec/models/diff_note_spec.rb
+++ b/spec/models/diff_note_spec.rb
@@ -119,7 +119,7 @@ describe DiffNote, models: true do
context "when the merge request's diff refs don't match that of the diff note" do
before do
- allow(subject.noteable).to receive(:diff_refs).and_return(commit.diff_refs)
+ allow(subject.noteable).to receive(:diff_sha_refs).and_return(commit.diff_refs)
end
it "returns false" do
@@ -168,7 +168,7 @@ describe DiffNote, models: true do
context "when the note is outdated" do
before do
- allow(merge_request).to receive(:diff_refs).and_return(commit.diff_refs)
+ allow(merge_request).to receive(:diff_sha_refs).and_return(commit.diff_refs)
end
it "uses the DiffPositionUpdateService" do
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index a0e3c26e542..21d22c776e9 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -686,4 +686,28 @@ describe MergeRequest, models: true do
subject.reload_diff
end
end
+
+ describe "#diff_sha_refs" do
+ context "with diffs" do
+ subject { create(:merge_request, :with_diffs) }
+
+ it "does not touch the repository" do
+ subject # Instantiate the object
+
+ expect_any_instance_of(Repository).not_to receive(:commit)
+
+ subject.diff_sha_refs
+ end
+
+ it "returns expected diff_refs" do
+ expected_diff_refs = Gitlab::Diff::DiffRefs.new(
+ base_sha: subject.merge_request_diff.base_commit_sha,
+ start_sha: subject.merge_request_diff.start_commit_sha,
+ head_sha: subject.merge_request_diff.head_commit_sha
+ )
+
+ expect(subject.diff_sha_refs).to eq(expected_diff_refs)
+ end
+ end
+ end
end