Commit 32cc3b3c authored by Eugenia Grieff's avatar Eugenia Grieff

Add service to cache group issues count

- Replace count in group template
parent 92c36c07
......@@ -620,6 +620,18 @@ class Group < Namespace
Gitlab::ServiceDesk.supported? && all_projects.service_desk_enabled.exists?
end
# rubocop: disable CodeReuse/ServiceClass
def open_issues_count(current_user = nil)
Groups::OpenIssuesCountService.new(self, current_user).count
end
# rubocop: enable CodeReuse/ServiceClass
# rubocop: disable CodeReuse/ServiceClass
def update_group_issues_counter_cache
Groups::OpenIssuesCountService.new(self).refresh_cache
end
# rubocop: enable CodeReuse/ServiceClass
private
def update_two_factor_requirement
......
# frozen_string_literal: true
module Groups
# Service class for counting and caching the number of open issues of a group.
class OpenIssuesCountService < OpenIssuesCountBaseService
include Gitlab::Utils::StrongMemoize
PUBLIC_COUNT_KEY = 'group_public_open_issues_count'
TOTAL_COUNT_KEY = 'group_total_open_issues_count'
def cache_options
super.merge({ expires_in: 24.hours })
end
def self.query(group, user: nil, public_only: true)
IssuesFinder.new(user, group_id: group.id, state: 'opened', non_archived: true, include_subgroups: true, public_only: public_only).execute
end
end
end
# frozen_string_literal: true
class IssuablesCountService < BaseCountService
# The version of the cache format. This should be bumped whenever the
# underlying logic changes. This removes the need for explicitly flushing
# all caches.
VERSION = 1
def initialize(parent)
@parent = parent
end
def relation_for_count
self.class.query(@parent.id)
end
def cache_key_name
raise(
NotImplementedError,
'"cache_key_name" must be implemented and return a String'
)
end
def cache_key(key = nil)
cache_key = key || cache_key_name
['parents', 'count_service', VERSION, @parent.id, cache_key]
end
def self.query(parent_ids)
raise(
NotImplementedError,
'"query" must be implemented and return an ActiveRecord::Relation'
)
end
end
# frozen_string_literal: true
# Service class for counting and caching the number of open issues of a group or a project.
class OpenIssuesCountBaseService < IssuablesCountService
include Gitlab::Utils::StrongMemoize
# Cache keys used to store issues count
PUBLIC_COUNT_KEY = ''
TOTAL_COUNT_KEY = ''
def initialize(group, user = nil)
@user = user
super(group)
end
def cache_key_name
public_only? ? PUBLIC_COUNT_KEY : TOTAL_COUNT_KEY
end
def public_only?
!user_is_at_least_reporter?
end
def relation_for_count
self.class.query(@parent, user: @user, public_only: public_only?)
end
def user_is_at_least_reporter?
strong_memoize(:user_is_at_least_reporter) do
@user && @parent.member?(@user, Gitlab::Access::REPORTER)
end
end
def public_count_cache_key
cache_key(PUBLIC_COUNT_KEY)
end
def total_count_cache_key
cache_key(TOTAL_COUNT_KEY)
end
# rubocop: disable CodeReuse/ActiveRecord
def refresh_cache(&block)
if block_given?
super(&block)
else
count_grouped_by_confidential = self.class.query(@parent, user: @user, public_only: false).group(:confidential).count
public_count = count_grouped_by_confidential[false] || 0
total_count = public_count + (count_grouped_by_confidential[true] || 0)
update_cache_for_key(group_public_count_cache_key) do
public_count
end
update_cache_for_key(group_total_count_cache_key) do
total_count
end
end
end
def self.query(parent, user: nil, public_only: true)
raise(
NotImplementedError,
'"query" must be implemented and return an ActiveRecord::Relation'
)
end
end
- issues_count = group_issues_count(state: 'opened')
- merge_requests_count = group_merge_requests_count(state: 'opened')
.nav-sidebar{ class: ("sidebar-collapsed-desktop" if collapsed_sidebar?), **tracking_attrs('groups_side_navigation', 'render', 'groups_side_navigation') }
......@@ -54,14 +53,16 @@
= sprite_icon('issues')
%span.nav-item-name
= _('Issues')
%span.badge.badge-pill.count= number_with_delimiter(issues_count)
%span.badge.badge-pill.count
= number_with_delimiter(@group.open_issues_count(current_user))
%ul.sidebar-sub-level-items{ data: { qa_selector: 'group_issues_sidebar_submenu'} }
= nav_link(path: ['groups#issues', 'labels#index', 'milestones#index', 'iterations#index'], html_options: { class: "fly-out-top-item" } ) do
= link_to issues_group_path(@group) do
%strong.fly-out-top-item-name
= _('Issues')
%span.badge.badge-pill.count.issue_counter.fly-out-badge= number_with_delimiter(issues_count)
%span.badge.badge-pill.count.issue_counter.fly-out-badge
= number_with_delimiter(@group.open_issues_count(current_user))
%li.divider.fly-out-top-item
= nav_link(path: 'groups#issues', html_options: { class: 'home' }) do
......
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