summaryrefslogtreecommitdiff
path: root/app/models/namespace/root_storage_statistics.rb
blob: 5723a823e988fb309f5041ad9d8005c7cec08e08 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# frozen_string_literal: true

class Namespace::RootStorageStatistics < ApplicationRecord
  SNIPPETS_SIZE_STAT_NAME = 'snippets_size'.freeze
  STATISTICS_ATTRIBUTES = %W(
    storage_size
    repository_size
    wiki_size
    lfs_objects_size
    build_artifacts_size
    packages_size
    #{SNIPPETS_SIZE_STAT_NAME}
    pipeline_artifacts_size
  ).freeze

  self.primary_key = :namespace_id

  belongs_to :namespace
  has_one :route, through: :namespace

  scope :for_namespace_ids, ->(namespace_ids) { where(namespace_id: namespace_ids) }

  delegate :all_projects, to: :namespace

  def recalculate!
    update!(merged_attributes)
  end

  private

  def merged_attributes
    attributes_from_project_statistics.merge!(attributes_from_personal_snippets) { |key, v1, v2| v1 + v2 }
  end

  def attributes_from_project_statistics
    from_project_statistics
      .take
      .attributes
      .slice(*STATISTICS_ATTRIBUTES)
  end

  def from_project_statistics
    all_projects
      .joins('INNER JOIN project_statistics ps ON ps.project_id  = projects.id')
      .select(
        'COALESCE(SUM(ps.storage_size), 0) AS storage_size',
        'COALESCE(SUM(ps.repository_size), 0) AS repository_size',
        'COALESCE(SUM(ps.wiki_size), 0) AS wiki_size',
        'COALESCE(SUM(ps.lfs_objects_size), 0) AS lfs_objects_size',
        'COALESCE(SUM(ps.build_artifacts_size), 0) AS build_artifacts_size',
        'COALESCE(SUM(ps.packages_size), 0) AS packages_size',
        "COALESCE(SUM(ps.snippets_size), 0) AS #{SNIPPETS_SIZE_STAT_NAME}",
        'COALESCE(SUM(ps.pipeline_artifacts_size), 0) AS pipeline_artifacts_size'
      )
  end

  def attributes_from_personal_snippets
    # Return if the type of namespace does not belong to a user
    return {} unless namespace.type.nil?

    from_personal_snippets.take.slice(SNIPPETS_SIZE_STAT_NAME)
  end

  def from_personal_snippets
    PersonalSnippet
      .joins('INNER JOIN snippet_statistics s ON s.snippet_id = snippets.id')
      .where(author: namespace.owner_id)
      .select("COALESCE(SUM(s.repository_size), 0) AS #{SNIPPETS_SIZE_STAT_NAME}")
  end
end