summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYorick Peterse <yorickpeterse@gmail.com>2016-03-08 17:38:23 +0100
committerYorick Peterse <yorickpeterse@gmail.com>2016-03-08 18:19:40 +0100
commitcb5a5ba09588af866aed595d960755bf4ced4483 (patch)
tree138d5dd36460bf07ed2665f42c8a8d9534ae821e
parent149a52b10f5d5715ad5868add8ae0d4d6389d46d (diff)
downloadgitlab-ce-cb5a5ba09588af866aed595d960755bf4ced4483.tar.gz
Cache & flush tag/branch counts
The methods used for this are Repository#tag_count and Repository#branch_count which cache their output in Redis as well as memoizing it in an instance variable. Both methods have a corresponding methods/hooks to flush the caches at the right time.
-rw-r--r--app/models/repository.rb33
-rw-r--r--app/services/git_tag_push_service.rb2
-rw-r--r--app/views/projects/branches/destroy.js.haml2
-rw-r--r--app/views/projects/commits/_head.html.haml4
-rw-r--r--spec/models/repository_spec.rb47
-rw-r--r--spec/services/delete_tag_service_spec.rb26
6 files changed, 104 insertions, 10 deletions
diff --git a/app/models/repository.rb b/app/models/repository.rb
index ff48f993d42..d3ca268a659 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -160,7 +160,7 @@ class Repository
end
def rm_tag(tag_name)
- expire_tags_cache
+ before_remove_tag
gitlab_shell.rm_tag(path_with_namespace, tag_name)
end
@@ -183,6 +183,14 @@ class Repository
end
end
+ def branch_count
+ @branch_count ||= cache.fetch(:branch_count) { raw_repository.branch_count }
+ end
+
+ def tag_count
+ @tag_count ||= cache.fetch(:tag_count) { raw_repository.rugged.tags.count }
+ end
+
# Return repo size in megabytes
# Cached in redis
def size
@@ -278,6 +286,16 @@ class Repository
@has_visible_content = nil
end
+ def expire_branch_count_cache
+ cache.expire(:branch_count)
+ @branch_count = nil
+ end
+
+ def expire_tag_count_cache
+ cache.expire(:tag_count)
+ @tag_count = nil
+ end
+
def rebuild_cache
cache_keys.each do |key|
cache.expire(key)
@@ -313,9 +331,16 @@ class Repository
expire_root_ref_cache
end
- # Runs code before creating a new tag.
- def before_create_tag
+ # Runs code before pushing (= creating or removing) a tag.
+ def before_push_tag
expire_cache
+ expire_tag_count_cache
+ end
+
+ # Runs code before removing a tag.
+ def before_remove_tag
+ expire_tags_cache
+ expire_tag_count_cache
end
# Runs code after a repository has been forked/imported.
@@ -331,11 +356,13 @@ class Repository
# Runs code after a new branch has been created.
def after_create_branch
expire_has_visible_content_cache
+ expire_branch_count_cache
end
# Runs code after an existing branch has been removed.
def after_remove_branch
expire_has_visible_content_cache
+ expire_branch_count_cache
end
def method_missing(m, *args, &block)
diff --git a/app/services/git_tag_push_service.rb b/app/services/git_tag_push_service.rb
index a62c5fc4fc4..c88c7672805 100644
--- a/app/services/git_tag_push_service.rb
+++ b/app/services/git_tag_push_service.rb
@@ -2,7 +2,7 @@ class GitTagPushService
attr_accessor :project, :user, :push_data
def execute(project, user, oldrev, newrev, ref)
- project.repository.before_create_tag
+ project.repository.before_push_tag
@project, @user = project, user
@push_data = build_push_data(oldrev, newrev, ref)
diff --git a/app/views/projects/branches/destroy.js.haml b/app/views/projects/branches/destroy.js.haml
index 882a4d0c5e2..a21ddaf4930 100644
--- a/app/views/projects/branches/destroy.js.haml
+++ b/app/views/projects/branches/destroy.js.haml
@@ -1 +1 @@
-$('.js-totalbranch-count').html("#{@repository.branches.size}")
+$('.js-totalbranch-count').html("#{@repository.branch_count}")
diff --git a/app/views/projects/commits/_head.html.haml b/app/views/projects/commits/_head.html.haml
index 498c5e05b32..7a5b0d993db 100644
--- a/app/views/projects/commits/_head.html.haml
+++ b/app/views/projects/commits/_head.html.haml
@@ -15,9 +15,9 @@
= nav_link(html_options: {class: branches_tab_class}) do
= link_to namespace_project_branches_path(@project.namespace, @project) do
Branches
- %span.badge.js-totalbranch-count= @repository.branches.size
+ %span.badge.js-totalbranch-count= @repository.branch_count
= nav_link(controller: [:tags, :releases]) do
= link_to namespace_project_tags_path(@project.namespace, @project) do
Tags
- %span.badge.js-totaltags-count= @repository.tags.length
+ %span.badge.js-totaltags-count= @repository.tag_count
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index 150422ac349..7af80704690 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -405,7 +405,7 @@ describe Repository, models: true do
end
end
- describe '#expire_branch_ache' do
+ describe '#expire_branch_cache' do
# This method is private but we need it for testing purposes. Sadly there's
# no other proper way of testing caching operations.
let(:cache) { repository.send(:cache) }
@@ -556,11 +556,12 @@ describe Repository, models: true do
end
end
- describe '#before_create_tag' do
+ describe '#before_push_tag' do
it 'flushes the cache' do
expect(repository).to receive(:expire_cache)
+ expect(repository).to receive(:expire_tag_count_cache)
- repository.before_create_tag
+ repository.before_push_tag
end
end
@@ -607,4 +608,44 @@ describe Repository, models: true do
expect(repository.main_language).to be_nil
end
end
+
+ describe '#before_remove_tag' do
+ it 'flushes the tag cache' do
+ expect(repository).to receive(:expire_tag_count_cache)
+
+ repository.before_remove_tag
+ end
+ end
+
+ describe '#branch_count' do
+ it 'returns the number of branches' do
+ expect(repository.branch_count).to be_an_instance_of(Fixnum)
+ end
+ end
+
+ describe '#tag_count' do
+ it 'returns the number of tags' do
+ expect(repository.tag_count).to be_an_instance_of(Fixnum)
+ end
+ end
+
+ describe '#expire_branch_count_cache' do
+ let(:cache) { repository.send(:cache) }
+
+ it 'expires the cache' do
+ expect(cache).to receive(:expire).with(:branch_count)
+
+ repository.expire_branch_count_cache
+ end
+ end
+
+ describe '#expire_tag_count_cache' do
+ let(:cache) { repository.send(:cache) }
+
+ it 'expires the cache' do
+ expect(cache).to receive(:expire).with(:tag_count)
+
+ repository.expire_tag_count_cache
+ end
+ end
end
diff --git a/spec/services/delete_tag_service_spec.rb b/spec/services/delete_tag_service_spec.rb
new file mode 100644
index 00000000000..5b7ba521812
--- /dev/null
+++ b/spec/services/delete_tag_service_spec.rb
@@ -0,0 +1,26 @@
+require 'spec_helper'
+
+describe DeleteTagService, services: true do
+ let(:project) { create(:project) }
+ let(:repository) { project.repository }
+ let(:user) { create(:user) }
+ let(:service) { described_class.new(project, user) }
+
+ let(:tag) { double(:tag, name: '8.5', target: 'abc123') }
+
+ describe '#execute' do
+ before do
+ allow(repository).to receive(:find_tag).and_return(tag)
+ end
+
+ it 'removes the tag' do
+ expect_any_instance_of(Gitlab::Shell).to receive(:rm_tag).
+ and_return(true)
+
+ expect(repository).to receive(:before_remove_tag)
+ expect(service).to receive(:success)
+
+ service.execute('8.5')
+ end
+ end
+end