Commit 2bae697a authored by Vijay Hawoldar's avatar Vijay Hawoldar

Refactor NamespaceStatistics into CE

So that we can calculate dependency proxy size at the namespace level,
this refactors the NamespaceStatistics model into CE to make it
available outside of EE

Changelog: changed
parent 56c44a68
...@@ -43,6 +43,7 @@ class Namespace < ApplicationRecord ...@@ -43,6 +43,7 @@ class Namespace < ApplicationRecord
has_many :projects, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent has_many :projects, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_many :project_statistics has_many :project_statistics
has_one :namespace_settings, inverse_of: :namespace, class_name: 'NamespaceSetting', autosave: true has_one :namespace_settings, inverse_of: :namespace, class_name: 'NamespaceSetting', autosave: true
has_one :namespace_statistics
has_one :namespace_route, foreign_key: :namespace_id, autosave: false, inverse_of: :namespace, class_name: 'Route' has_one :namespace_route, foreign_key: :namespace_id, autosave: false, inverse_of: :namespace, class_name: 'Route'
has_many :namespace_members, foreign_key: :member_namespace_id, inverse_of: :member_namespace, class_name: 'Member' has_many :namespace_members, foreign_key: :member_namespace_id, inverse_of: :member_namespace, class_name: 'Member'
......
...@@ -27,10 +27,17 @@ class Namespace::RootStorageStatistics < ApplicationRecord ...@@ -27,10 +27,17 @@ class Namespace::RootStorageStatistics < ApplicationRecord
update!(merged_attributes) update!(merged_attributes)
end end
def self.namespace_statistics_attributes
%w(storage_size dependency_proxy_size)
end
private private
def merged_attributes def merged_attributes
attributes_from_project_statistics.merge!(attributes_from_personal_snippets) { |key, v1, v2| v1 + v2 } attributes_from_project_statistics.merge!(
attributes_from_personal_snippets,
attributes_from_namespace_statistics
) { |key, v1, v2| v1 + v2 }
end end
def attributes_from_project_statistics def attributes_from_project_statistics
...@@ -68,6 +75,27 @@ class Namespace::RootStorageStatistics < ApplicationRecord ...@@ -68,6 +75,27 @@ class Namespace::RootStorageStatistics < ApplicationRecord
.where(author: namespace.owner_id) .where(author: namespace.owner_id)
.select("COALESCE(SUM(s.repository_size), 0) AS #{SNIPPETS_SIZE_STAT_NAME}") .select("COALESCE(SUM(s.repository_size), 0) AS #{SNIPPETS_SIZE_STAT_NAME}")
end end
def from_namespace_statistics
namespace
.self_and_descendants
.joins("INNER JOIN namespace_statistics ns ON ns.namespace_id = namespaces.id")
.select(
'COALESCE(SUM(ns.storage_size), 0) AS storage_size',
'COALESCE(SUM(ns.dependency_proxy_size), 0) AS dependency_proxy_size'
)
end
def attributes_from_namespace_statistics
# At the moment, only groups can have some storage data because of dependency proxy assets.
# Therefore, if the namespace is not a group one, there is no need to perform
# the query. If this changes in the future and we add some sort of resource to
# users that it's store in NamespaceStatistics, we will need to remove this
# guard clause.
return {} unless namespace.group_namespace?
from_namespace_statistics.take.slice(*self.class.namespace_statistics_attributes)
end
end end
Namespace::RootStorageStatistics.prepend_mod_with('Namespace::RootStorageStatistics') Namespace::RootStorageStatistics.prepend_mod_with('Namespace::RootStorageStatistics')
# frozen_string_literal: true # frozen_string_literal: true
class NamespaceStatistics < ApplicationRecord class NamespaceStatistics < ApplicationRecord # rubocop:disable Gitlab/NamespacedClass
include AfterCommitQueue include AfterCommitQueue
belongs_to :namespace belongs_to :namespace
...@@ -15,13 +15,11 @@ class NamespaceStatistics < ApplicationRecord ...@@ -15,13 +15,11 @@ class NamespaceStatistics < ApplicationRecord
delegate :group_namespace?, to: :namespace delegate :group_namespace?, to: :namespace
COLUMNS_TO_REFRESH = [:wiki_size].freeze
def refresh!(only: []) def refresh!(only: [])
return if Gitlab::Database.read_only? return if Gitlab::Database.read_only?
return unless group_namespace? return unless group_namespace?
COLUMNS_TO_REFRESH.each do |column| self.class.columns_to_refresh.each do |column|
if only.empty? || only.include?(column) if only.empty? || only.include?(column)
public_send("update_#{column}") # rubocop:disable GitlabSecurity/PublicSend public_send("update_#{column}") # rubocop:disable GitlabSecurity/PublicSend
end end
...@@ -31,21 +29,21 @@ class NamespaceStatistics < ApplicationRecord ...@@ -31,21 +29,21 @@ class NamespaceStatistics < ApplicationRecord
end end
def update_storage_size def update_storage_size
self.storage_size = wiki_size self.storage_size = dependency_proxy_size
end end
def update_wiki_size def update_dependency_proxy_size
return unless group_wiki_available? return unless group_namespace?
self.wiki_size = namespace.wiki.repository.size.megabytes self.dependency_proxy_size = namespace.dependency_proxy_manifests.sum(:size) + namespace.dependency_proxy_blobs.sum(:size)
end end
private def self.columns_to_refresh
[:dependency_proxy_size]
def group_wiki_available?
group_namespace? && namespace.feature_available?(:group_wikis)
end end
private
def update_root_storage_statistics def update_root_storage_statistics
return unless group_namespace? return unless group_namespace?
...@@ -54,3 +52,5 @@ class NamespaceStatistics < ApplicationRecord ...@@ -54,3 +52,5 @@ class NamespaceStatistics < ApplicationRecord
end end
end end
end end
NamespaceStatistics.prepend_mod_with('NamespaceStatistics')
...@@ -23,7 +23,6 @@ module EE ...@@ -23,7 +23,6 @@ module EE
prepended do prepended do
include EachBatch include EachBatch
has_one :namespace_statistics
has_one :namespace_limit, inverse_of: :namespace has_one :namespace_limit, inverse_of: :namespace
has_one :gitlab_subscription has_one :gitlab_subscription
has_one :elasticsearch_indexed_namespace has_one :elasticsearch_indexed_namespace
......
...@@ -6,36 +6,22 @@ module EE ...@@ -6,36 +6,22 @@ module EE
extend ActiveSupport::Concern extend ActiveSupport::Concern
extend ::Gitlab::Utils::Override extend ::Gitlab::Utils::Override
prepended do class_methods do
NAMESPACE_STATISTICS_ATTRIBUTES = %w[storage_size wiki_size].freeze extend ::Gitlab::Utils::Override
end
override :merged_attributes override :namespace_statistics_attributes
def merged_attributes def namespace_statistics_attributes
super.merge!(attributes_from_namespace_statistics) { |key, v1, v2| v1 + v2 } super << 'wiki_size'
end
end end
private private
def attributes_from_namespace_statistics override :from_namespace_statistics
# At the moment, only groups can have some storage data because of group wikis.
# Therefore, if the namespace is not a group one, there is no need to perform
# the query. If this changes in the future and we add some sort of resource to
# users that it's store in NamespaceStatistics, we will need to remove this
# guard clause.
return {} unless namespace.group_namespace?
from_namespace_statistics.take.slice(*NAMESPACE_STATISTICS_ATTRIBUTES)
end
def from_namespace_statistics def from_namespace_statistics
namespace super.select(
.self_and_descendants 'COALESCE(SUM(ns.wiki_size), 0) AS wiki_size'
.joins("INNER JOIN namespace_statistics ns ON ns.namespace_id = namespaces.id") )
.select(
'COALESCE(SUM(ns.storage_size), 0) AS storage_size',
'COALESCE(SUM(ns.wiki_size), 0) AS wiki_size'
)
end end
end end
end end
......
# frozen_string_literal: true
module EE
module NamespaceStatistics
extend ActiveSupport::Concern
extend ::Gitlab::Utils::Override
def update_storage_size
super
self.storage_size += wiki_size
end
def update_wiki_size
return unless group_wiki_available?
self.wiki_size = namespace.wiki.repository.size.megabytes
end
class_methods do
extend ::Gitlab::Utils::Override
override :columns_to_refresh
def columns_to_refresh
super << :wiki_size
end
end
private
def group_wiki_available?
group_namespace? && namespace.licensed_feature_available?(:group_wikis)
end
end
end
...@@ -22,7 +22,7 @@ RSpec.describe EE::Namespace::RootStorageStatistics do ...@@ -22,7 +22,7 @@ RSpec.describe EE::Namespace::RootStorageStatistics do
let(:namespace) { root_group } let(:namespace) { root_group }
it 'aggregates namespace statistics' do it 'aggregates namespace wiki statistics' do
# This group is not a descendant of the root_group so it shouldn't be included in the final stats. # This group is not a descendant of the root_group so it shouldn't be included in the final stats.
other_group = create(:group) other_group = create(:group)
create(:namespace_statistics, namespace: other_group, storage_size: 500, wiki_size: 500) create(:namespace_statistics, namespace: other_group, storage_size: 500, wiki_size: 500)
...@@ -31,23 +31,9 @@ RSpec.describe EE::Namespace::RootStorageStatistics do ...@@ -31,23 +31,9 @@ RSpec.describe EE::Namespace::RootStorageStatistics do
root_storage_statistics.reload root_storage_statistics.reload
total_repository_size = project_stat1.repository_size + project_stat2.repository_size
total_lfs_objects_size = project_stat1.lfs_objects_size + project_stat2.lfs_objects_size
total_build_artifacts_size = project_stat1.build_artifacts_size + project_stat2.build_artifacts_size
total_packages_size = project_stat1.packages_size + project_stat2.packages_size
total_snippets_size = project_stat1.snippets_size + project_stat2.snippets_size
total_pipeline_artifacts_size = project_stat1.pipeline_artifacts_size + project_stat2.pipeline_artifacts_size
total_uploads_size = project_stat1.uploads_size + project_stat2.uploads_size
total_wiki_size = project_stat1.wiki_size + project_stat2.wiki_size + root_namespace_stat.wiki_size + group1_namespace_stat.wiki_size + group2_namespace_stat.wiki_size + subgroup1_namespace_stat.wiki_size total_wiki_size = project_stat1.wiki_size + project_stat2.wiki_size + root_namespace_stat.wiki_size + group1_namespace_stat.wiki_size + group2_namespace_stat.wiki_size + subgroup1_namespace_stat.wiki_size
total_storage_size = project_stat1.storage_size + project_stat2.storage_size + root_namespace_stat.storage_size + group1_namespace_stat.storage_size + group2_namespace_stat.storage_size + subgroup1_namespace_stat.storage_size total_storage_size = project_stat1.storage_size + project_stat2.storage_size + root_namespace_stat.storage_size + group1_namespace_stat.storage_size + group2_namespace_stat.storage_size + subgroup1_namespace_stat.storage_size
expect(root_storage_statistics.repository_size).to eq(total_repository_size)
expect(root_storage_statistics.lfs_objects_size).to eq(total_lfs_objects_size)
expect(root_storage_statistics.build_artifacts_size).to eq(total_build_artifacts_size)
expect(root_storage_statistics.packages_size).to eq(total_packages_size)
expect(root_storage_statistics.snippets_size).to eq(total_snippets_size)
expect(root_storage_statistics.pipeline_artifacts_size).to eq(total_pipeline_artifacts_size)
expect(root_storage_statistics.uploads_size).to eq(total_uploads_size)
expect(root_storage_statistics.storage_size).to eq(total_storage_size) expect(root_storage_statistics.storage_size).to eq(total_storage_size)
expect(root_storage_statistics.wiki_size).to eq(total_wiki_size) expect(root_storage_statistics.wiki_size).to eq(total_wiki_size)
end end
......
...@@ -14,7 +14,6 @@ RSpec.describe Namespace do ...@@ -14,7 +14,6 @@ RSpec.describe Namespace do
let!(:premium_plan) { create(:premium_plan) } let!(:premium_plan) { create(:premium_plan) }
let!(:ultimate_plan) { create(:ultimate_plan) } let!(:ultimate_plan) { create(:ultimate_plan) }
it { is_expected.to have_one(:namespace_statistics) }
it { is_expected.to have_one(:namespace_limit) } it { is_expected.to have_one(:namespace_limit) }
it { is_expected.to have_one(:elasticsearch_indexed_namespace) } it { is_expected.to have_one(:elasticsearch_indexed_namespace) }
it { is_expected.to have_one :upcoming_reconciliation } it { is_expected.to have_one :upcoming_reconciliation }
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe NamespaceStatistics do
include WikiHelpers
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group) }
let_it_be(:group_wiki) do
create(:group_wiki, group: group).tap do |group_wiki|
group_wiki.create_page('home', 'test content')
end
end
describe '#refresh!' do
let(:namespace) { group }
let(:statistics) { create(:namespace_statistics, namespace: namespace) }
let(:columns) { [] }
subject(:refresh!) { statistics.refresh!(only: columns) }
shared_examples 'creates the namespace statistics' do
specify do
expect(statistics).to receive(:save!)
refresh!
end
end
context 'when no option is passed' do
it 'updates the wiki size' do
expect(statistics).to receive(:update_wiki_size)
refresh!
end
it_behaves_like 'creates the namespace statistics'
end
context 'when wiki_size option is passed' do
let(:columns) { [:wiki_size] }
it 'updates the wiki size' do
expect(statistics).to receive(:update_wiki_size)
refresh!
end
it_behaves_like 'creates the namespace statistics'
end
end
describe '#update_storage_size' do
let_it_be(:statistics, reload: true) { create(:namespace_statistics, namespace: group, dependency_proxy_size: 2, storage_size: 2) }
it 'adds wiki_size to the storage_size' do
statistics.wiki_size = 3
statistics.update_storage_size
expect(statistics.storage_size).to eq 5
end
end
describe '#update_wiki_size' do
let_it_be(:statistics, reload: true) { create(:namespace_statistics, namespace: group) }
subject(:update_wiki_size) { statistics.update_wiki_size }
context 'when group_wikis feature is not enabled' do
it 'does not update the wiki size' do
stub_group_wikis(false)
update_wiki_size
expect(statistics.wiki_size).to be_zero
end
end
context 'when group_wikis feature is enabled' do
before do
stub_group_wikis(true)
end
it 'updates the wiki size' do
update_wiki_size
expect(statistics.wiki_size).to eq group.wiki.repository.size.megabytes.to_i
end
context 'when namespace does not belong to a group' do
let(:statistics) { create(:namespace_statistics, namespace: user.namespace) }
it 'does not update the wiki size' do
expect(statistics).not_to receive(:wiki)
update_wiki_size
expect(statistics.wiki_size).to be_zero
end
end
end
end
end
...@@ -28,24 +28,24 @@ RSpec.describe Namespace::RootStorageStatistics, type: :model do ...@@ -28,24 +28,24 @@ RSpec.describe Namespace::RootStorageStatistics, type: :model do
let(:project1) { create(:project, namespace: namespace) } let(:project1) { create(:project, namespace: namespace) }
let(:project2) { create(:project, namespace: namespace) } let(:project2) { create(:project, namespace: namespace) }
let!(:stat1) { create(:project_statistics, project: project1, with_data: true, size_multiplier: 100) } let!(:project_stat1) { create(:project_statistics, project: project1, with_data: true, size_multiplier: 100) }
let!(:stat2) { create(:project_statistics, project: project2, with_data: true, size_multiplier: 200) } let!(:project_stat2) { create(:project_statistics, project: project2, with_data: true, size_multiplier: 200) }
shared_examples 'data refresh' do shared_examples 'project data refresh' do
it 'aggregates project statistics' do it 'aggregates project statistics' do
root_storage_statistics.recalculate! root_storage_statistics.recalculate!
root_storage_statistics.reload root_storage_statistics.reload
total_repository_size = stat1.repository_size + stat2.repository_size total_repository_size = project_stat1.repository_size + project_stat2.repository_size
total_wiki_size = stat1.wiki_size + stat2.wiki_size total_wiki_size = project_stat1.wiki_size + project_stat2.wiki_size
total_lfs_objects_size = stat1.lfs_objects_size + stat2.lfs_objects_size total_lfs_objects_size = project_stat1.lfs_objects_size + project_stat2.lfs_objects_size
total_build_artifacts_size = stat1.build_artifacts_size + stat2.build_artifacts_size total_build_artifacts_size = project_stat1.build_artifacts_size + project_stat2.build_artifacts_size
total_packages_size = stat1.packages_size + stat2.packages_size total_packages_size = project_stat1.packages_size + project_stat2.packages_size
total_storage_size = stat1.storage_size + stat2.storage_size total_storage_size = project_stat1.storage_size + project_stat2.storage_size
total_snippets_size = stat1.snippets_size + stat2.snippets_size total_snippets_size = project_stat1.snippets_size + project_stat2.snippets_size
total_pipeline_artifacts_size = stat1.pipeline_artifacts_size + stat2.pipeline_artifacts_size total_pipeline_artifacts_size = project_stat1.pipeline_artifacts_size + project_stat2.pipeline_artifacts_size
total_uploads_size = stat1.uploads_size + stat2.uploads_size total_uploads_size = project_stat1.uploads_size + project_stat2.uploads_size
expect(root_storage_statistics.repository_size).to eq(total_repository_size) expect(root_storage_statistics.repository_size).to eq(total_repository_size)
expect(root_storage_statistics.wiki_size).to eq(total_wiki_size) expect(root_storage_statistics.wiki_size).to eq(total_wiki_size)
...@@ -83,7 +83,7 @@ RSpec.describe Namespace::RootStorageStatistics, type: :model do ...@@ -83,7 +83,7 @@ RSpec.describe Namespace::RootStorageStatistics, type: :model do
end end
end end
it_behaves_like 'data refresh' it_behaves_like 'project data refresh'
it_behaves_like 'does not include personal snippets' it_behaves_like 'does not include personal snippets'
context 'with subgroups' do context 'with subgroups' do
...@@ -93,19 +93,81 @@ RSpec.describe Namespace::RootStorageStatistics, type: :model do ...@@ -93,19 +93,81 @@ RSpec.describe Namespace::RootStorageStatistics, type: :model do
let(:project1) { create(:project, namespace: subgroup1) } let(:project1) { create(:project, namespace: subgroup1) }
let(:project2) { create(:project, namespace: subgroup2) } let(:project2) { create(:project, namespace: subgroup2) }
it_behaves_like 'data refresh' it_behaves_like 'project data refresh'
it_behaves_like 'does not include personal snippets' it_behaves_like 'does not include personal snippets'
end end
context 'with a group namespace' do
let_it_be(:root_group) { create(:group) }
let_it_be(:group1) { create(:group, parent: root_group) }
let_it_be(:subgroup1) { create(:group, parent: group1) }
let_it_be(:group2) { create(:group, parent: root_group) }
let_it_be(:root_namespace_stat) { create(:namespace_statistics, namespace: root_group, storage_size: 100, dependency_proxy_size: 100) }
let_it_be(:group1_namespace_stat) { create(:namespace_statistics, namespace: group1, storage_size: 200, dependency_proxy_size: 200) }
let_it_be(:group2_namespace_stat) { create(:namespace_statistics, namespace: group2, storage_size: 300, dependency_proxy_size: 300) }
let_it_be(:subgroup1_namespace_stat) { create(:namespace_statistics, namespace: subgroup1, storage_size: 300, dependency_proxy_size: 100) }
let(:namespace) { root_group }
it 'aggregates namespace statistics' do
# This group is not a descendant of the root_group so it shouldn't be included in the final stats.
other_group = create(:group)
create(:namespace_statistics, namespace: other_group, storage_size: 500, dependency_proxy_size: 500)
root_storage_statistics.recalculate!
total_repository_size = project_stat1.repository_size + project_stat2.repository_size
total_lfs_objects_size = project_stat1.lfs_objects_size + project_stat2.lfs_objects_size
total_build_artifacts_size = project_stat1.build_artifacts_size + project_stat2.build_artifacts_size
total_packages_size = project_stat1.packages_size + project_stat2.packages_size
total_snippets_size = project_stat1.snippets_size + project_stat2.snippets_size
total_pipeline_artifacts_size = project_stat1.pipeline_artifacts_size + project_stat2.pipeline_artifacts_size
total_uploads_size = project_stat1.uploads_size + project_stat2.uploads_size
total_wiki_size = project_stat1.wiki_size + project_stat2.wiki_size
total_dependency_proxy_size = root_namespace_stat.dependency_proxy_size + group1_namespace_stat.dependency_proxy_size + group2_namespace_stat.dependency_proxy_size + subgroup1_namespace_stat.dependency_proxy_size
total_storage_size = project_stat1.storage_size + project_stat2.storage_size + root_namespace_stat.storage_size + group1_namespace_stat.storage_size + group2_namespace_stat.storage_size + subgroup1_namespace_stat.storage_size
expect(root_storage_statistics.repository_size).to eq(total_repository_size)
expect(root_storage_statistics.lfs_objects_size).to eq(total_lfs_objects_size)
expect(root_storage_statistics.build_artifacts_size).to eq(total_build_artifacts_size)
expect(root_storage_statistics.packages_size).to eq(total_packages_size)
expect(root_storage_statistics.snippets_size).to eq(total_snippets_size)
expect(root_storage_statistics.pipeline_artifacts_size).to eq(total_pipeline_artifacts_size)
expect(root_storage_statistics.uploads_size).to eq(total_uploads_size)
expect(root_storage_statistics.dependency_proxy_size).to eq(total_dependency_proxy_size)
expect(root_storage_statistics.wiki_size).to eq(total_wiki_size)
expect(root_storage_statistics.storage_size).to eq(total_storage_size)
end
it 'works when there are no namespace statistics' do
NamespaceStatistics.delete_all
root_storage_statistics.recalculate!
total_storage_size = project_stat1.storage_size + project_stat2.storage_size
expect(root_storage_statistics.storage_size).to eq(total_storage_size)
end
end
context 'with a personal namespace' do context 'with a personal namespace' do
let_it_be(:user) { create(:user) } let_it_be(:user) { create(:user) }
let(:namespace) { user.namespace } let(:namespace) { user.namespace }
it_behaves_like 'data refresh' it_behaves_like 'project data refresh'
it 'does not aggregate namespace statistics' do
create(:namespace_statistics, namespace: user.namespace, storage_size: 200, dependency_proxy_size: 200)
root_storage_statistics.recalculate!
expect(root_storage_statistics.storage_size).to eq(project_stat1.storage_size + project_stat2.storage_size)
expect(root_storage_statistics.dependency_proxy_size).to eq(0)
end
context 'when user has personal snippets' do context 'when user has personal snippets' do
let(:total_project_snippets_size) { stat1.snippets_size + stat2.snippets_size } let(:total_project_snippets_size) { project_stat1.snippets_size + project_stat2.snippets_size }
it 'aggregates personal and project snippets size' do it 'aggregates personal and project snippets size' do
# This is just a a snippet authored by other user # This is just a a snippet authored by other user
......
...@@ -23,6 +23,7 @@ RSpec.describe Namespace do ...@@ -23,6 +23,7 @@ RSpec.describe Namespace do
it { is_expected.to have_one :root_storage_statistics } it { is_expected.to have_one :root_storage_statistics }
it { is_expected.to have_one :aggregation_schedule } it { is_expected.to have_one :aggregation_schedule }
it { is_expected.to have_one :namespace_settings } it { is_expected.to have_one :namespace_settings }
it { is_expected.to have_one(:namespace_statistics) }
it { is_expected.to have_many :custom_emoji } it { is_expected.to have_many :custom_emoji }
it { is_expected.to have_one :package_setting_relation } it { is_expected.to have_one :package_setting_relation }
it { is_expected.to have_one :onboarding_progress } it { is_expected.to have_one :onboarding_progress }
......
...@@ -3,15 +3,8 @@ ...@@ -3,15 +3,8 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe NamespaceStatistics do RSpec.describe NamespaceStatistics do
include WikiHelpers
let_it_be(:user) { create(:user) } let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group) } let_it_be(:group) { create(:group) }
let_it_be(:group_wiki) do
create(:group_wiki, group: group).tap do |group_wiki|
group_wiki.create_page('home', 'test content')
end
end
it { is_expected.to belong_to(:namespace) } it { is_expected.to belong_to(:namespace) }
...@@ -22,7 +15,7 @@ RSpec.describe NamespaceStatistics do ...@@ -22,7 +15,7 @@ RSpec.describe NamespaceStatistics do
let(:statistics) { create(:namespace_statistics, namespace: namespace) } let(:statistics) { create(:namespace_statistics, namespace: namespace) }
let(:columns) { [] } let(:columns) { [] }
subject { statistics.refresh!(only: columns) } subject(:refresh!) { statistics.refresh!(only: columns) }
context 'when database is read_only' do context 'when database is read_only' do
it 'does not save the object' do it 'does not save the object' do
...@@ -30,7 +23,7 @@ RSpec.describe NamespaceStatistics do ...@@ -30,7 +23,7 @@ RSpec.describe NamespaceStatistics do
expect(statistics).not_to receive(:save!) expect(statistics).not_to receive(:save!)
subject refresh!
end end
end end
...@@ -40,7 +33,7 @@ RSpec.describe NamespaceStatistics do ...@@ -40,7 +33,7 @@ RSpec.describe NamespaceStatistics do
it 'does not save the object' do it 'does not save the object' do
expect(statistics).not_to receive(:save!) expect(statistics).not_to receive(:save!)
subject refresh!
end end
end end
...@@ -48,7 +41,7 @@ RSpec.describe NamespaceStatistics do ...@@ -48,7 +41,7 @@ RSpec.describe NamespaceStatistics do
specify do specify do
expect(statistics).to receive(:save!) expect(statistics).to receive(:save!)
subject refresh!
end end
end end
...@@ -56,31 +49,32 @@ RSpec.describe NamespaceStatistics do ...@@ -56,31 +49,32 @@ RSpec.describe NamespaceStatistics do
let(:columns) { [:foo] } let(:columns) { [:foo] }
it 'does not update any column' do it 'does not update any column' do
expect(statistics).not_to receive(:update_wiki_size) create(:dependency_proxy_manifest, group: namespace, size: 50)
subject expect(statistics).not_to receive(:update_dependency_proxy_size)
expect { refresh! }.not_to change { statistics.reload.storage_size }
end end
it_behaves_like 'creates the namespace statistics' it_behaves_like 'creates the namespace statistics'
end end
context 'when no option is passed' do context 'when no option is passed' do
it 'updates the wiki size' do it 'updates the dependency proxy size' do
expect(statistics).to receive(:update_wiki_size) expect(statistics).to receive(:update_dependency_proxy_size)
subject refresh!
end end
it_behaves_like 'creates the namespace statistics' it_behaves_like 'creates the namespace statistics'
end end
context 'when wiki_size option is passed' do context 'when dependency_proxy_size option is passed' do
let(:columns) { [:wiki_size] } let(:columns) { [:dependency_proxy_size] }
it 'updates the wiki size' do it 'updates the dependency proxy size' do
expect(statistics).to receive(:update_wiki_size) expect(statistics).to receive(:update_dependency_proxy_size)
subject refresh!
end end
it_behaves_like 'creates the namespace statistics' it_behaves_like 'creates the namespace statistics'
...@@ -90,8 +84,8 @@ RSpec.describe NamespaceStatistics do ...@@ -90,8 +84,8 @@ RSpec.describe NamespaceStatistics do
describe '#update_storage_size' do describe '#update_storage_size' do
let_it_be(:statistics, reload: true) { create(:namespace_statistics, namespace: group) } let_it_be(:statistics, reload: true) { create(:namespace_statistics, namespace: group) }
it 'sets storage_size to the wiki_size' do it 'sets storage_size to the dependency_proxy_size' do
statistics.wiki_size = 3 statistics.dependency_proxy_size = 3
statistics.update_storage_size statistics.update_storage_size
...@@ -99,48 +93,32 @@ RSpec.describe NamespaceStatistics do ...@@ -99,48 +93,32 @@ RSpec.describe NamespaceStatistics do
end end
end end
describe '#update_wiki_size' do describe '#update_dependency_proxy_size' do
let_it_be(:statistics, reload: true) { create(:namespace_statistics, namespace: group) } let_it_be(:statistics, reload: true) { create(:namespace_statistics, namespace: group) }
let_it_be(:dependency_proxy_manifest) { create(:dependency_proxy_manifest, group: group, size: 50) }
let_it_be(:dependency_proxy_blob) { create(:dependency_proxy_blob, group: group, size: 50) }
subject { statistics.update_wiki_size } subject(:update_dependency_proxy_size) { statistics.update_dependency_proxy_size }
context 'when group_wikis feature is not enabled' do
it 'does not update the wiki size' do
stub_group_wikis(false)
subject it 'updates the dependency proxy size' do
update_dependency_proxy_size
expect(statistics.wiki_size).to be_zero expect(statistics.dependency_proxy_size).to eq 100
end
end end
context 'when group_wikis feature is enabled enabled' do context 'when namespace does not belong to a group' do
before do let(:statistics) { create(:namespace_statistics, namespace: user.namespace) }
stub_group_wikis(true)
end
it 'updates the wiki size' do
subject
expect(statistics.wiki_size).to eq group.wiki.repository.size.megabytes.to_i
end
context 'when namespace does not belong to a group' do it 'does not update the dependency proxy size' do
let(:statistics) { create(:namespace_statistics, namespace: user.namespace) } update_dependency_proxy_size
it 'does not update the wiki size' do expect(statistics.dependency_proxy_size).to be_zero
expect(statistics).not_to receive(:wiki)
subject
expect(statistics.wiki_size).to be_zero
end
end end
end end
end end
context 'before saving statistics' do context 'before saving statistics' do
let(:statistics) { create(:namespace_statistics, namespace: group, wiki_size: 10) } let(:statistics) { create(:namespace_statistics, namespace: group, dependency_proxy_size: 10) }
it 'updates storage size' do it 'updates storage size' do
expect(statistics).to receive(:update_storage_size).and_call_original expect(statistics).to receive(:update_storage_size).and_call_original
...@@ -167,9 +145,9 @@ RSpec.describe NamespaceStatistics do ...@@ -167,9 +145,9 @@ RSpec.describe NamespaceStatistics do
context 'when storage_size is updated' do context 'when storage_size is updated' do
before do before do
# we have to update this value instead of `storage_size` because the before_save # we have to update this value instead of `storage_size` because the before_save
# hook we have. If we don't do it, storage_size will be set to the wiki_size value # hook we have. If we don't do it, storage_size will be set to the dependency_proxy_size value
# which is 0. # which is 0.
statistics.wiki_size = 10 statistics.dependency_proxy_size = 10
end end
it 'enqueues the job to update root storage statistics' do it 'enqueues the job to update root storage statistics' do
...@@ -193,7 +171,7 @@ RSpec.describe NamespaceStatistics do ...@@ -193,7 +171,7 @@ RSpec.describe NamespaceStatistics do
context 'when other columns are updated' do context 'when other columns are updated' do
it 'does not enqueue the job to update root storage statistics' do it 'does not enqueue the job to update root storage statistics' do
columns_to_update = NamespaceStatistics.columns_hash.except('id', 'namespace_id', 'wiki_size', 'storage_size').keys columns_to_update = NamespaceStatistics.columns_hash.reject { |k, _| %w(id namespace_id).include?(k) || k.include?('_size') }.keys
columns_to_update.each { |c| statistics[c] = 10 } columns_to_update.each { |c| statistics[c] = 10 }
expect(statistics).not_to receive(:update_root_storage_statistics) expect(statistics).not_to receive(:update_root_storage_statistics)
......
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