Merge branch 'forks-count-cache' into 'master'
Cache the number of forks of a project See merge request !13535
This commit is contained in:
commit
e645ab2233
14 changed files with 141 additions and 1 deletions
|
@ -196,7 +196,6 @@ class Project < ActiveRecord::Base
|
|||
accepts_nested_attributes_for :import_data
|
||||
|
||||
delegate :name, to: :owner, allow_nil: true, prefix: true
|
||||
delegate :count, to: :forks, prefix: true
|
||||
delegate :members, to: :team, prefix: true
|
||||
delegate :add_user, :add_users, to: :team
|
||||
delegate :add_guest, :add_reporter, :add_developer, :add_master, to: :team
|
||||
|
@ -1396,6 +1395,10 @@ class Project < ActiveRecord::Base
|
|||
# @deprecated cannot remove yet because it has an index with its name in elasticsearch
|
||||
alias_method :path_with_namespace, :full_path
|
||||
|
||||
def forks_count
|
||||
Projects::ForksCountService.new(self).count
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def cross_namespace_reference?(from)
|
||||
|
|
|
@ -128,6 +128,8 @@ module Projects
|
|||
project.repository.before_delete
|
||||
|
||||
Repository.new(wiki_path, project, disk_path: repo_path).before_delete
|
||||
|
||||
Projects::ForksCountService.new(project).delete_cache
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -21,11 +21,17 @@ module Projects
|
|||
builds_access_level = @project.project_feature.builds_access_level
|
||||
new_project.project_feature.update_attributes(builds_access_level: builds_access_level)
|
||||
|
||||
refresh_forks_count
|
||||
|
||||
new_project
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def refresh_forks_count
|
||||
Projects::ForksCountService.new(@project).refresh_cache
|
||||
end
|
||||
|
||||
def allowed_visibility_level
|
||||
project_level = @project.visibility_level
|
||||
|
||||
|
|
30
app/services/projects/forks_count_service.rb
Normal file
30
app/services/projects/forks_count_service.rb
Normal file
|
@ -0,0 +1,30 @@
|
|||
module Projects
|
||||
# Service class for getting and caching the number of forks of a project.
|
||||
class ForksCountService
|
||||
def initialize(project)
|
||||
@project = project
|
||||
end
|
||||
|
||||
def count
|
||||
Rails.cache.fetch(cache_key) { uncached_count }
|
||||
end
|
||||
|
||||
def refresh_cache
|
||||
Rails.cache.write(cache_key, uncached_count)
|
||||
end
|
||||
|
||||
def delete_cache
|
||||
Rails.cache.delete(cache_key)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def uncached_count
|
||||
@project.forks.count
|
||||
end
|
||||
|
||||
def cache_key
|
||||
['projects', @project.id, 'forks_count']
|
||||
end
|
||||
end
|
||||
end
|
|
@ -13,7 +13,13 @@ module Projects
|
|||
::MergeRequests::CloseService.new(@project, @current_user).execute(mr)
|
||||
end
|
||||
|
||||
refresh_forks_count(@project.forked_from_project)
|
||||
|
||||
@project.forked_project_link.destroy
|
||||
end
|
||||
|
||||
def refresh_forks_count(project)
|
||||
Projects::ForksCountService.new(project).refresh_cache
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
5
changelogs/unreleased/forks-count-cache.yml
Normal file
5
changelogs/unreleased/forks-count-cache.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Cache the number of forks of a project
|
||||
merge_request: 13535
|
||||
author:
|
||||
type: other
|
|
@ -351,6 +351,8 @@ module API
|
|||
|
||||
if user_project.forked_from_project.nil?
|
||||
user_project.create_forked_project_link(forked_to_project_id: user_project.id, forked_from_project_id: forked_from_project.id)
|
||||
|
||||
::Projects::ForksCountService.new(forked_from_project).refresh_cache
|
||||
else
|
||||
render_api_error!("Project already forked", 409)
|
||||
end
|
||||
|
|
|
@ -388,6 +388,8 @@ module API
|
|||
|
||||
if user_project.forked_from_project.nil?
|
||||
user_project.create_forked_project_link(forked_to_project_id: user_project.id, forked_from_project_id: forked_from_project.id)
|
||||
|
||||
::Projects::ForksCountService.new(forked_from_project).refresh_cache
|
||||
else
|
||||
render_api_error!("Project already forked", 409)
|
||||
end
|
||||
|
|
|
@ -2310,4 +2310,14 @@ describe Project do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#forks_count' do
|
||||
it 'returns the number of forks' do
|
||||
project = build(:project)
|
||||
|
||||
allow(project.forks).to receive(:count).and_return(1)
|
||||
|
||||
expect(project.forks_count).to eq(1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1065,6 +1065,14 @@ describe API::Projects do
|
|||
expect(project_fork_target.forked?).to be_truthy
|
||||
end
|
||||
|
||||
it 'refreshes the forks count cachce' do
|
||||
expect(project_fork_source.forks_count).to be_zero
|
||||
|
||||
post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", admin)
|
||||
|
||||
expect(project_fork_source.forks_count).to eq(1)
|
||||
end
|
||||
|
||||
it 'fails if forked_from project which does not exist' do
|
||||
post api("/projects/#{project_fork_target.id}/fork/9999", admin)
|
||||
expect(response).to have_http_status(404)
|
||||
|
|
|
@ -1004,6 +1004,14 @@ describe API::V3::Projects do
|
|||
expect(project_fork_target.forked?).to be_truthy
|
||||
end
|
||||
|
||||
it 'refreshes the forks count cachce' do
|
||||
expect(project_fork_source.forks_count).to be_zero
|
||||
|
||||
post v3_api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", admin)
|
||||
|
||||
expect(project_fork_source.forks_count).to eq(1)
|
||||
end
|
||||
|
||||
it 'fails if forked_from project which does not exist' do
|
||||
post v3_api("/projects/#{project_fork_target.id}/fork/9999", admin)
|
||||
expect(response).to have_http_status(404)
|
||||
|
|
|
@ -50,6 +50,14 @@ describe Projects::ForkService do
|
|||
|
||||
expect(@from_project.avatar.file).to be_exists
|
||||
end
|
||||
|
||||
it 'flushes the forks count cache of the source project' do
|
||||
expect(@from_project.forks_count).to be_zero
|
||||
|
||||
fork_project(@from_project, @to_user)
|
||||
|
||||
expect(@from_project.forks_count).to eq(1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
40
spec/services/projects/forks_count_service_spec.rb
Normal file
40
spec/services/projects/forks_count_service_spec.rb
Normal file
|
@ -0,0 +1,40 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Projects::ForksCountService do
|
||||
let(:project) { build(:project, id: 42) }
|
||||
let(:service) { described_class.new(project) }
|
||||
|
||||
describe '#count' do
|
||||
it 'returns the number of forks' do
|
||||
allow(service).to receive(:uncached_count).and_return(1)
|
||||
|
||||
expect(service.count).to eq(1)
|
||||
end
|
||||
|
||||
it 'caches the forks count', :use_clean_rails_memory_store_caching do
|
||||
expect(service).to receive(:uncached_count).once.and_return(1)
|
||||
|
||||
2.times { service.count }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#refresh_cache', :use_clean_rails_memory_store_caching do
|
||||
it 'refreshes the cache' do
|
||||
expect(service).to receive(:uncached_count).once.and_return(1)
|
||||
|
||||
service.refresh_cache
|
||||
|
||||
expect(service.count).to eq(1)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#delete_cache', :use_clean_rails_memory_store_caching do
|
||||
it 'removes the cache' do
|
||||
expect(service).to receive(:uncached_count).twice.and_return(1)
|
||||
|
||||
service.count
|
||||
service.delete_cache
|
||||
service.count
|
||||
end
|
||||
end
|
||||
end
|
|
@ -29,4 +29,14 @@ describe Projects::UnlinkForkService do
|
|||
|
||||
subject.execute
|
||||
end
|
||||
|
||||
it 'refreshes the forks count cache of the source project' do
|
||||
source = fork_project.forked_from_project
|
||||
|
||||
expect(source.forks_count).to eq(1)
|
||||
|
||||
subject.execute
|
||||
|
||||
expect(source.forks_count).to be_zero
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue