Commit 2c6e34bc authored by Robert Speicher's avatar Robert Speicher

Merge branch 'repository-caching-refactor' into 'master'

Refactor Repository Caching

Related issue: https://gitlab.com/gitlab-org/gitlab-ce/issues/13515

See merge request !2936
parents 01160fc0 a10678e7
...@@ -801,10 +801,7 @@ class Project < ActiveRecord::Base ...@@ -801,10 +801,7 @@ class Project < ActiveRecord::Base
end end
def change_head(branch) def change_head(branch)
# Cached divergent commit counts are based on repository head repository.before_change_head
repository.expire_branch_cache
repository.expire_root_ref_cache
gitlab_shell.update_repository_head(self.path_with_namespace, branch) gitlab_shell.update_repository_head(self.path_with_namespace, branch)
reload_default_branch reload_default_branch
end end
......
...@@ -245,15 +245,6 @@ class Repository ...@@ -245,15 +245,6 @@ class Repository
expire_emptiness_caches if empty? expire_emptiness_caches if empty?
end end
# Expires _all_ caches, including those that would normally only be expired
# under specific conditions.
def expire_all_caches!
expire_cache
expire_root_ref_cache
expire_emptiness_caches
expire_has_visible_content_cache
end
def expire_branch_cache(branch_name = nil) def expire_branch_cache(branch_name = nil)
# When we push to the root branch we have to flush the cache for all other # When we push to the root branch we have to flush the cache for all other
# branches as their statistics are based on the commits relative to the # branches as their statistics are based on the commits relative to the
...@@ -307,6 +298,46 @@ class Repository ...@@ -307,6 +298,46 @@ class Repository
cache.expire(:branch_names) cache.expire(:branch_names)
end end
# Runs code just before a repository is deleted.
def before_delete
expire_cache if exists?
expire_root_ref_cache
expire_emptiness_caches
end
# Runs code just before the HEAD of a repository is changed.
def before_change_head
# Cached divergent commit counts are based on repository head
expire_branch_cache
expire_root_ref_cache
end
# Runs code before creating a new tag.
def before_create_tag
expire_cache
end
# Runs code after a repository has been forked/imported.
def after_import
expire_emptiness_caches
end
# Runs code after a new commit has been pushed.
def after_push_commit(branch_name)
expire_cache(branch_name)
end
# Runs code after a new branch has been created.
def after_create_branch
expire_has_visible_content_cache
end
# Runs code after an existing branch has been removed.
def after_remove_branch
expire_has_visible_content_cache
end
def method_missing(m, *args, &block) def method_missing(m, *args, &block)
if m == :lookup && !block_given? if m == :lookup && !block_given?
lookup_cache[m] ||= {} lookup_cache[m] ||= {}
......
...@@ -16,13 +16,13 @@ class GitPushService < BaseService ...@@ -16,13 +16,13 @@ class GitPushService < BaseService
# 5. Executes the project's services # 5. Executes the project's services
# #
def execute def execute
@project.repository.expire_cache(branch_name) @project.repository.after_push_commit(branch_name)
if push_remove_branch? if push_remove_branch?
@project.repository.expire_has_visible_content_cache @project.repository.after_remove_branch
@push_commits = [] @push_commits = []
elsif push_to_new_branch? elsif push_to_new_branch?
@project.repository.expire_has_visible_content_cache @project.repository.after_create_branch
# Re-find the pushed commits. # Re-find the pushed commits.
if is_default_branch? if is_default_branch?
......
...@@ -2,7 +2,7 @@ class GitTagPushService ...@@ -2,7 +2,7 @@ class GitTagPushService
attr_accessor :project, :user, :push_data attr_accessor :project, :user, :push_data
def execute(project, user, oldrev, newrev, ref) def execute(project, user, oldrev, newrev, ref)
project.repository.expire_cache project.repository.before_create_tag
@project, @user = project, user @project, @user = project, user
@push_data = build_push_data(oldrev, newrev, ref) @push_data = build_push_data(oldrev, newrev, ref)
......
...@@ -76,11 +76,9 @@ module Projects ...@@ -76,11 +76,9 @@ module Projects
end end
def flush_caches(project, wiki_path) def flush_caches(project, wiki_path)
project.repository.expire_all_caches! if project.repository.exists? project.repository.before_delete
wiki_repo = Repository.new(wiki_path, project) Repository.new(wiki_path, project).before_delete
wiki_repo.expire_all_caches! if wiki_repo.exists?
end end
end end
end end
...@@ -27,7 +27,7 @@ class RepositoryForkWorker ...@@ -27,7 +27,7 @@ class RepositoryForkWorker
return return
end end
project.repository.expire_emptiness_caches project.repository.after_import
project.import_finish project.import_finish
end end
end end
...@@ -18,7 +18,7 @@ class RepositoryImportWorker ...@@ -18,7 +18,7 @@ class RepositoryImportWorker
return return
end end
project.repository.expire_emptiness_caches project.repository.after_import
project.import_finish project.import_finish
end end
end end
...@@ -362,14 +362,14 @@ describe Repository, models: true do ...@@ -362,14 +362,14 @@ describe Repository, models: true do
repository.expire_cache('master') repository.expire_cache('master')
end end
it 'expires the emptiness cache for an empty repository' do it 'expires the emptiness caches for an empty repository' do
expect(repository).to receive(:empty?).and_return(true) expect(repository).to receive(:empty?).and_return(true)
expect(repository).to receive(:expire_emptiness_caches) expect(repository).to receive(:expire_emptiness_caches)
repository.expire_cache repository.expire_cache
end end
it 'does not expire the emptiness cache for a non-empty repository' do it 'does not expire the emptiness caches for a non-empty repository' do
expect(repository).to receive(:empty?).and_return(false) expect(repository).to receive(:empty?).and_return(false)
expect(repository).to_not receive(:expire_emptiness_caches) expect(repository).to_not receive(:expire_emptiness_caches)
...@@ -464,4 +464,108 @@ describe Repository, models: true do ...@@ -464,4 +464,108 @@ describe Repository, models: true do
expect(repository.blob_at_branch('master', 'files/ruby/feature.rb')).not_to be_present expect(repository.blob_at_branch('master', 'files/ruby/feature.rb')).not_to be_present
end end
end end
describe '#before_delete' do
describe 'when a repository does not exist' do
before do
allow(repository).to receive(:exists?).and_return(false)
end
it 'does not flush caches that depend on repository data' do
expect(repository).to_not receive(:expire_cache)
repository.before_delete
end
it 'flushes the root ref cache' do
expect(repository).to receive(:expire_root_ref_cache)
repository.before_delete
end
it 'flushes the emptiness caches' do
expect(repository).to receive(:expire_emptiness_caches)
repository.before_delete
end
end
describe 'when a repository exists' do
before do
allow(repository).to receive(:exists?).and_return(true)
end
it 'flushes the caches that depend on repository data' do
expect(repository).to receive(:expire_cache)
repository.before_delete
end
it 'flushes the root ref cache' do
expect(repository).to receive(:expire_root_ref_cache)
repository.before_delete
end
it 'flushes the emptiness caches' do
expect(repository).to receive(:expire_emptiness_caches)
repository.before_delete
end
end
end
describe '#before_change_head' do
it 'flushes the branch cache' do
expect(repository).to receive(:expire_branch_cache)
repository.before_change_head
end
it 'flushes the root ref cache' do
expect(repository).to receive(:expire_root_ref_cache)
repository.before_change_head
end
end
describe '#before_create_tag' do
it 'flushes the cache' do
expect(repository).to receive(:expire_cache)
repository.before_create_tag
end
end
describe '#after_import' do
it 'flushes the emptiness cachess' do
expect(repository).to receive(:expire_emptiness_caches)
repository.after_import
end
end
describe '#after_push_commit' do
it 'flushes the cache' do
expect(repository).to receive(:expire_cache).with('master')
repository.after_push_commit('master')
end
end
describe '#after_create_branch' do
it 'flushes the visible content cache' do
expect(repository).to receive(:expire_has_visible_content_cache)
repository.after_create_branch
end
end
describe '#after_remove_branch' do
it 'flushes the visible content cache' do
expect(repository).to receive(:expire_has_visible_content_cache)
repository.after_remove_branch
end
end
end end
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