Commit dc28ada0 authored by Sean McGivern's avatar Sean McGivern

Merge branch 'zj-memoization-mr-commits' into 'master'

Use memoization for commits on diffs

See merge request gitlab-org/gitlab-ce!15857
parents 49a9de11 428c38a2
...@@ -8,6 +8,7 @@ class MergeRequest < ActiveRecord::Base ...@@ -8,6 +8,7 @@ class MergeRequest < ActiveRecord::Base
include ManualInverseAssociation include ManualInverseAssociation
include EachBatch include EachBatch
include ThrottledTouch include ThrottledTouch
include Gitlab::Utils::StrongMemoize
ignore_column :locked_at, ignore_column :locked_at,
:ref_fetched :ref_fetched
...@@ -53,6 +54,7 @@ class MergeRequest < ActiveRecord::Base ...@@ -53,6 +54,7 @@ class MergeRequest < ActiveRecord::Base
after_create :ensure_merge_request_diff, unless: :importing? after_create :ensure_merge_request_diff, unless: :importing?
after_update :reload_diff_if_branch_changed after_update :reload_diff_if_branch_changed
after_update :clear_memoized_shas
# When this attribute is true some MR validation is ignored # When this attribute is true some MR validation is ignored
# It allows us to close or modify broken merge requests # It allows us to close or modify broken merge requests
...@@ -387,13 +389,17 @@ class MergeRequest < ActiveRecord::Base ...@@ -387,13 +389,17 @@ class MergeRequest < ActiveRecord::Base
end end
def source_branch_head def source_branch_head
return unless source_project strong_memoize(:source_branch_head) do
if source_project && source_branch_ref
source_project.repository.commit(source_branch_ref) if source_branch_ref source_project.repository.commit(source_branch_ref)
end
end
end end
def target_branch_head def target_branch_head
target_project.repository.commit(target_branch_ref) strong_memoize(:target_branch_head) do
target_project.repository.commit(target_branch_ref)
end
end end
def branch_merge_base_commit def branch_merge_base_commit
...@@ -525,6 +531,13 @@ class MergeRequest < ActiveRecord::Base ...@@ -525,6 +531,13 @@ class MergeRequest < ActiveRecord::Base
end end
end end
def clear_memoized_shas
@target_branch_sha = @source_branch_sha = nil
clear_memoization(:source_branch_head)
clear_memoization(:target_branch_head)
end
def reload_diff_if_branch_changed def reload_diff_if_branch_changed
if (source_branch_changed? || target_branch_changed?) && if (source_branch_changed? || target_branch_changed?) &&
(source_branch_head && target_branch_head) (source_branch_head && target_branch_head)
......
...@@ -104,19 +104,19 @@ class MergeRequestDiff < ActiveRecord::Base ...@@ -104,19 +104,19 @@ class MergeRequestDiff < ActiveRecord::Base
def base_commit def base_commit
return unless base_commit_sha return unless base_commit_sha
project.commit(base_commit_sha) project.commit_by(oid: base_commit_sha)
end end
def start_commit def start_commit
return unless start_commit_sha return unless start_commit_sha
project.commit(start_commit_sha) project.commit_by(oid: start_commit_sha)
end end
def head_commit def head_commit
return unless head_commit_sha return unless head_commit_sha
project.commit(head_commit_sha) project.commit_by(oid: head_commit_sha)
end end
def commit_shas def commit_shas
......
---
title: Cache commits for MergeRequest diffs
merge_request:
author:
type: performance
...@@ -19,6 +19,8 @@ module Gitlab ...@@ -19,6 +19,8 @@ module Gitlab
commit_message: commit_message || default_commit_message commit_message: commit_message || default_commit_message
} }
resolver.resolve_conflicts(user, files, args) resolver.resolve_conflicts(user, files, args)
ensure
@merge_request.clear_memoized_shas
end end
def files def files
......
...@@ -11,6 +11,8 @@ module Gitlab ...@@ -11,6 +11,8 @@ module Gitlab
# #
# We could write it like: # We could write it like:
# #
# include Gitlab::Utils::StrongMemoize
#
# def trigger_from_token # def trigger_from_token
# strong_memoize(:trigger) do # strong_memoize(:trigger) do
# Ci::Trigger.find_by_token(params[:token].to_s) # Ci::Trigger.find_by_token(params[:token].to_s)
...@@ -18,14 +20,22 @@ module Gitlab ...@@ -18,14 +20,22 @@ module Gitlab
# end # end
# #
def strong_memoize(name) def strong_memoize(name)
ivar_name = "@#{name}" if instance_variable_defined?(ivar(name))
instance_variable_get(ivar(name))
if instance_variable_defined?(ivar_name)
instance_variable_get(ivar_name)
else else
instance_variable_set(ivar_name, yield) instance_variable_set(ivar(name), yield)
end end
end end
def clear_memoization(name)
remove_instance_variable(ivar(name)) if instance_variable_defined?(ivar(name))
end
private
def ivar(name)
"@#{name}"
end
end end
end end
end end
...@@ -49,4 +49,16 @@ describe Gitlab::Utils::StrongMemoize do ...@@ -49,4 +49,16 @@ describe Gitlab::Utils::StrongMemoize do
end end
end end
end end
describe '#clear_memoization' do
let(:value) { 'mepmep' }
it 'removes the instance variable' do
object.method_name
object.clear_memoization(:method_name)
expect(object.instance_variable_defined?(:@method_name)).to be(false)
end
end
end end
...@@ -124,6 +124,7 @@ describe MergeRequest do ...@@ -124,6 +124,7 @@ describe MergeRequest do
context 'when the target branch does not exist' do context 'when the target branch does not exist' do
before do before do
project.repository.rm_branch(subject.author, subject.target_branch) project.repository.rm_branch(subject.author, subject.target_branch)
subject.clear_memoized_shas
end end
it 'returns nil' do it 'returns nil' do
...@@ -733,7 +734,7 @@ describe MergeRequest do ...@@ -733,7 +734,7 @@ describe MergeRequest do
before do before do
project.repository.raw_repository.delete_branch(subject.target_branch) project.repository.raw_repository.delete_branch(subject.target_branch)
subject.reload subject.clear_memoized_shas
end end
it 'does not crash' do it 'does not crash' do
...@@ -1468,6 +1469,7 @@ describe MergeRequest do ...@@ -1468,6 +1469,7 @@ describe MergeRequest do
context 'when the target branch does not exist' do context 'when the target branch does not exist' do
before do before do
subject.project.repository.rm_branch(subject.author, subject.target_branch) subject.project.repository.rm_branch(subject.author, subject.target_branch)
subject.clear_memoized_shas
end end
it 'returns nil' do it 'returns nil' 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