gitlab-org--gitlab-foss/lib/gitlab/conflict/file_collection.rb
Zeger-Jan van de Weg 3ab026b7d6
Use memoization for commits on diffs
The Gitaly CommitService is being hammered by n + 1 calls, mostly when
finding commits. This leads to this gRPC being turned of on production:
https://gitlab.com/gitlab-org/gitaly/issues/514#note_48991378

Hunting down where it came from, most of them were due to
MergeRequest#show. To prove this, I set a script to request the
MergeRequest#show page 50 times. The GDK was being scraped by
Prometheus, where we have metrics on controller#action and their Gitaly
calls performed. On both occations I've restarted the full GDK so all
caches had to be rebuild.

Current master, 806a68a81f, needed 435 requests
After this commit, 154 requests
2017-12-12 16:28:26 +01:00

60 lines
1.8 KiB
Ruby

module Gitlab
module Conflict
class FileCollection
attr_reader :merge_request, :resolver
def initialize(merge_request)
source_repo = merge_request.source_project.repository.raw
our_commit = merge_request.source_branch_head.raw
their_commit = merge_request.target_branch_head.raw
target_repo = merge_request.target_project.repository.raw
@resolver = Gitlab::Git::Conflict::Resolver.new(source_repo, our_commit, target_repo, their_commit)
@merge_request = merge_request
end
def resolve(user, commit_message, files)
args = {
source_branch: merge_request.source_branch,
target_branch: merge_request.target_branch,
commit_message: commit_message || default_commit_message
}
resolver.resolve_conflicts(user, files, args)
ensure
@merge_request.clear_memoized_shas
end
def files
@files ||= resolver.conflicts.map do |conflict_file|
Gitlab::Conflict::File.new(conflict_file, merge_request: merge_request)
end
end
def file_for_path(old_path, new_path)
files.find { |file| file.their_path == old_path && file.our_path == new_path }
end
def as_json(opts = nil)
{
target_branch: merge_request.target_branch,
source_branch: merge_request.source_branch,
commit_sha: merge_request.diff_head_sha,
commit_message: default_commit_message,
files: files
}
end
def default_commit_message
conflict_filenames = files.map do |conflict|
"# #{conflict.our_path}"
end
<<EOM.chomp
Merge branch '#{merge_request.target_branch}' into '#{merge_request.source_branch}'
# Conflicts:
#{conflict_filenames.join("\n")}
EOM
end
end
end
end