Commit 3180cf1c authored by Igor Drozdov's avatar Igor Drozdov

Perform FindTag RPC request for a single tag

Currently, we perform FindAllTags RPC even for a single tag
Using FindTag for single cases would be more efficient

Changelog: performance
parent ef947c73
...@@ -191,8 +191,12 @@ class Repository ...@@ -191,8 +191,12 @@ class Repository
end end
def find_tag(name) def find_tag(name)
if @tags.blank? && Feature.enabled?(:find_tag_via_gitaly, project, default_enabled: :yaml)
raw_repository.find_tag(name)
else
tags.find { |tag| tag.name == name } tags.find { |tag| tag.name == name }
end end
end
def ambiguous_ref?(ref) def ambiguous_ref?(ref)
tag_exists?(ref) && branch_exists?(ref) tag_exists?(ref) && branch_exists?(ref)
......
---
name: find_tag_via_gitaly
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70181
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/340899
milestone: '14.3'
type: development
group: group::source code
default_enabled: false
...@@ -127,6 +127,13 @@ module Gitlab ...@@ -127,6 +127,13 @@ module Gitlab
end end
end end
def find_tag(name)
wrapped_gitaly_errors do
gitaly_ref_client.find_tag(name)
end
rescue CommandError
end
def local_branches(sort_by: nil, pagination_params: nil) def local_branches(sort_by: nil, pagination_params: nil)
wrapped_gitaly_errors do wrapped_gitaly_errors do
gitaly_ref_client.local_branches(sort_by: sort_by, pagination_params: pagination_params) gitaly_ref_client.local_branches(sort_by: sort_by, pagination_params: pagination_params)
...@@ -604,10 +611,6 @@ module Gitlab ...@@ -604,10 +611,6 @@ module Gitlab
end end
end end
def find_tag(name)
tags.find { |tag| tag.name == name }
end
def merge_to_ref(user, **kwargs) def merge_to_ref(user, **kwargs)
wrapped_gitaly_errors do wrapped_gitaly_errors do
gitaly_operation_client.user_merge_to_ref(user, **kwargs) gitaly_operation_client.user_merge_to_ref(user, **kwargs)
......
...@@ -129,6 +129,21 @@ module Gitlab ...@@ -129,6 +129,21 @@ module Gitlab
Gitlab::Git::Branch.new(@repository, encode!(branch.name.dup), branch.target_commit.id, target_commit) Gitlab::Git::Branch.new(@repository, encode!(branch.name.dup), branch.target_commit.id, target_commit)
end end
def find_tag(tag_name)
return if tag_name.blank?
request = Gitaly::FindTagRequest.new(
repository: @gitaly_repo,
tag_name: encode_binary(tag_name)
)
response = GitalyClient.call(@repository.storage, :ref_service, :find_tag, request, timeout: GitalyClient.medium_timeout)
tag = response.tag
return unless tag
Gitlab::Git::Tag.new(@repository, tag)
end
def delete_refs(refs: [], except_with_prefixes: []) def delete_refs(refs: [], except_with_prefixes: [])
request = Gitaly::DeleteRefsRequest.new( request = Gitaly::DeleteRefsRequest.new(
repository: @gitaly_repo, repository: @gitaly_repo,
......
...@@ -92,6 +92,36 @@ RSpec.describe Gitlab::GitalyClient::RefService do ...@@ -92,6 +92,36 @@ RSpec.describe Gitlab::GitalyClient::RefService do
end end
end end
describe '#find_branch' do
it 'sends a find_branch message' do
expect_any_instance_of(Gitaly::RefService::Stub)
.to receive(:find_branch)
.with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash))
.and_return(double(branch: Gitaly::Branch.new(name: 'name', target_commit: build(:gitaly_commit))))
client.find_branch('name')
end
end
describe '#find_tag' do
it 'sends a find_tag message' do
expect_any_instance_of(Gitaly::RefService::Stub)
.to receive(:find_tag)
.with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash))
.and_return(double(tag: Gitaly::Tag.new))
client.find_tag('name')
end
context 'when tag is empty' do
it 'does not send a fing_tag message' do
expect_any_instance_of(Gitaly::RefService::Stub).not_to receive(:find_tag)
expect(client.find_tag('')).to be_nil
end
end
end
describe '#default_branch_name' do describe '#default_branch_name' do
it 'sends a find_default_branch_name message' do it 'sends a find_default_branch_name message' do
expect_any_instance_of(Gitaly::RefService::Stub) expect_any_instance_of(Gitaly::RefService::Stub)
......
...@@ -2366,6 +2366,42 @@ RSpec.describe Repository do ...@@ -2366,6 +2366,42 @@ RSpec.describe Repository do
end end
end end
describe '#find_tag' do
before do
allow(Gitlab::GitalyClient).to receive(:call).and_call_original
end
it 'finds a tag with specified name by performing FindTag request' do
expect(Gitlab::GitalyClient)
.to receive(:call).with(anything, :ref_service, :find_tag, anything, anything).and_call_original
expect(repository.find_tag('v1.1.0').name).to eq('v1.1.0')
end
it 'does not perform Gitaly call when tags are preloaded' do
repository.tags
expect(Gitlab::GitalyClient).not_to receive(:call)
expect(repository.find_tag('v1.1.0').name).to eq('v1.1.0')
end
it 'returns nil when tag does not exists' do
expect(repository.find_tag('does-not-exist')).to be_nil
end
context 'when find_tag_via_gitaly is disabled' do
it 'fetches all tags' do
stub_feature_flags(find_tag_via_gitaly: false)
expect(Gitlab::GitalyClient)
.to receive(:call).with(anything, :ref_service, :find_all_tags, anything, anything).and_call_original
expect(repository.find_tag('v1.1.0').name).to eq('v1.1.0')
end
end
end
describe '#avatar' do describe '#avatar' do
it 'returns nil if repo does not exist' do it 'returns nil if repo does not exist' do
allow(repository).to receive(:root_ref).and_raise(Gitlab::Git::Repository::NoRepository) allow(repository).to receive(:root_ref).and_raise(Gitlab::Git::Repository::NoRepository)
......
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