diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-02-18 13:34:06 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-02-18 13:34:06 +0300 |
commit | 859a6fb938bb9ee2a317c46dfa4fcc1af49608f0 (patch) | |
tree | d7f2700abe6b4ffcb2dcfc80631b2d87d0609239 /app/services/groups | |
parent | 446d496a6d000c73a304be52587cd9bbc7493136 (diff) |
Add latest changes from gitlab-org/gitlab@13-9-stable-eev13.9.0-rc42
Diffstat (limited to 'app/services/groups')
-rw-r--r-- | app/services/groups/import_export/export_service.rb | 56 | ||||
-rw-r--r-- | app/services/groups/import_export/import_service.rb | 52 | ||||
-rw-r--r-- | app/services/groups/open_issues_count_service.rb | 64 |
3 files changed, 126 insertions, 46 deletions
diff --git a/app/services/groups/import_export/export_service.rb b/app/services/groups/import_export/export_service.rb index abac0ffc5d9..a436aec1b39 100644 --- a/app/services/groups/import_export/export_service.rb +++ b/app/services/groups/import_export/export_service.rb @@ -12,40 +12,44 @@ module Groups end def async_execute - GroupExportWorker.perform_async(@current_user.id, @group.id, @params) + GroupExportWorker.perform_async(current_user.id, group.id, params) end def execute validate_user_permissions - remove_existing_export! if @group.export_file_exists? + remove_existing_export! if group.export_file_exists? save! ensure - remove_base_tmp_dir + remove_archive_tmp_dir end private + attr_reader :group, :current_user, :params attr_accessor :shared def validate_user_permissions - unless @current_user.can?(:admin_group, @group) - @shared.error(::Gitlab::ImportExport::Error.permission_error(@current_user, @group)) + unless current_user.can?(:admin_group, group) + shared.error(::Gitlab::ImportExport::Error.permission_error(current_user, group)) notify_error! end end def remove_existing_export! - import_export_upload = @group.import_export_upload + import_export_upload = group.import_export_upload import_export_upload.remove_export_file! import_export_upload.save end def save! - if savers.all?(&:save) + # We cannot include the file_saver with the other savers because + # it removes the tmp dir. This means that if we want to add new savers + # in EE the data won't be available. + if savers.all?(&:save) && file_saver.save notify_success else notify_error! @@ -53,36 +57,40 @@ module Groups end def savers - [version_saver, tree_exporter, file_saver] + [version_saver, tree_exporter] end def tree_exporter tree_exporter_class.new( - group: @group, - current_user: @current_user, - shared: @shared, - params: @params + group: group, + current_user: current_user, + shared: shared, + params: params ) end def tree_exporter_class - if ::Feature.enabled?(:group_export_ndjson, @group&.parent, default_enabled: true) + if ndjson? Gitlab::ImportExport::Group::TreeSaver else Gitlab::ImportExport::Group::LegacyTreeSaver end end + def ndjson? + ::Feature.enabled?(:group_export_ndjson, group&.parent, default_enabled: :yaml) + end + def version_saver Gitlab::ImportExport::VersionSaver.new(shared: shared) end def file_saver - Gitlab::ImportExport::Saver.new(exportable: @group, shared: @shared) + Gitlab::ImportExport::Saver.new(exportable: group, shared: shared) end - def remove_base_tmp_dir - FileUtils.rm_rf(shared.base_path) if shared&.base_path + def remove_archive_tmp_dir + FileUtils.rm_rf(shared.archive_path) if shared&.archive_path end def notify_error! @@ -94,22 +102,22 @@ module Groups def notify_success @logger.info( message: 'Group Export succeeded', - group_id: @group.id, - group_name: @group.name + group_id: group.id, + group_name: group.name ) - notification_service.group_was_exported(@group, @current_user) + notification_service.group_was_exported(group, current_user) end def notify_error @logger.error( message: 'Group Export failed', - group_id: @group.id, - group_name: @group.name, - errors: @shared.errors.join(', ') + group_id: group.id, + group_name: group.name, + errors: shared.errors.join(', ') ) - notification_service.group_was_not_exported(@group, @current_user, @shared.errors) + notification_service.group_was_not_exported(group, current_user, shared.errors) end def notification_service @@ -118,3 +126,5 @@ module Groups end end end + +Groups::ImportExport::ExportService.prepend_if_ee('EE::Groups::ImportExport::ExportService') diff --git a/app/services/groups/import_export/import_service.rb b/app/services/groups/import_export/import_service.rb index a0ddc50e5e0..bf3f09f22d4 100644 --- a/app/services/groups/import_export/import_service.rb +++ b/app/services/groups/import_export/import_service.rb @@ -3,7 +3,7 @@ module Groups module ImportExport class ImportService - attr_reader :current_user, :group, :params + attr_reader :current_user, :group, :shared def initialize(group:, user:) @group = group @@ -26,10 +26,10 @@ module Groups end def execute - if valid_user_permissions? && import_file && restorer.restore + if valid_user_permissions? && import_file && restorers.all?(&:restore) notify_success - @group + group else notify_error! end @@ -43,37 +43,41 @@ module Groups def import_file @import_file ||= Gitlab::ImportExport::FileImporter.import( - importable: @group, + importable: group, archive_file: nil, - shared: @shared + shared: shared ) end - def restorer - @restorer ||= + def restorers + [tree_restorer] + end + + def tree_restorer + @tree_restorer ||= if ndjson? Gitlab::ImportExport::Group::TreeRestorer.new( - user: @current_user, - shared: @shared, - group: @group + user: current_user, + shared: shared, + group: group ) else Gitlab::ImportExport::Group::LegacyTreeRestorer.new( - user: @current_user, - shared: @shared, - group: @group, + user: current_user, + shared: shared, + group: group, group_hash: nil ) end end def ndjson? - ::Feature.enabled?(:group_import_ndjson, @group&.parent, default_enabled: true) && - File.exist?(File.join(@shared.export_path, 'tree/groups/_all.ndjson')) + ::Feature.enabled?(:group_import_ndjson, group&.parent, default_enabled: true) && + File.exist?(File.join(shared.export_path, 'tree/groups/_all.ndjson')) end def remove_import_file - upload = @group.import_export_upload + upload = group.import_export_upload return unless upload&.import_file&.file @@ -85,7 +89,7 @@ module Groups if current_user.can?(:admin_group, group) true else - @shared.error(::Gitlab::ImportExport::Error.permission_error(current_user, group)) + shared.error(::Gitlab::ImportExport::Error.permission_error(current_user, group)) false end @@ -93,16 +97,16 @@ module Groups def notify_success @logger.info( - group_id: @group.id, - group_name: @group.name, + group_id: group.id, + group_name: group.name, message: 'Group Import/Export: Import succeeded' ) end def notify_error @logger.error( - group_id: @group.id, - group_name: @group.name, + group_id: group.id, + group_name: group.name, message: "Group Import/Export: Errors occurred, see '#{Gitlab::ErrorTracking::Logger.file_name}' for details" ) end @@ -110,12 +114,14 @@ module Groups def notify_error! notify_error - raise Gitlab::ImportExport::Error.new(@shared.errors.to_sentence) + raise Gitlab::ImportExport::Error.new(shared.errors.to_sentence) end def remove_base_tmp_dir - FileUtils.rm_rf(@shared.base_path) + FileUtils.rm_rf(shared.base_path) end end end end + +Groups::ImportExport::ImportService.prepend_if_ee('EE::Groups::ImportExport::ImportService') diff --git a/app/services/groups/open_issues_count_service.rb b/app/services/groups/open_issues_count_service.rb new file mode 100644 index 00000000000..db1ca09212a --- /dev/null +++ b/app/services/groups/open_issues_count_service.rb @@ -0,0 +1,64 @@ +# frozen_string_literal: true + +module Groups + # Service class for counting and caching the number of open issues of a group. + class OpenIssuesCountService < BaseCountService + include Gitlab::Utils::StrongMemoize + + VERSION = 1 + PUBLIC_COUNT_KEY = 'group_public_open_issues_count' + TOTAL_COUNT_KEY = 'group_total_open_issues_count' + CACHED_COUNT_THRESHOLD = 1000 + EXPIRATION_TIME = 24.hours + + attr_reader :group, :user + + def initialize(group, user = nil) + @group = group + @user = user + end + + # Reads count value from cache and return it if present. + # If empty or expired, #uncached_count will calculate the issues count for the group and + # compare it with the threshold. If it is greater, it will be written to the cache and returned. + # If below, it will be returned without being cached. + # This results in only caching large counts and calculating the rest with every call to maintain + # accuracy. + def count + cached_count = Rails.cache.read(cache_key) + return cached_count unless cached_count.blank? + + refreshed_count = uncached_count + update_cache_for_key(cache_key) { refreshed_count } if refreshed_count > CACHED_COUNT_THRESHOLD + refreshed_count + end + + def cache_key(key = nil) + ['groups', 'open_issues_count_service', VERSION, group.id, cache_key_name] + end + + private + + def cache_options + super.merge({ expires_in: EXPIRATION_TIME }) + end + + def cache_key_name + public_only? ? PUBLIC_COUNT_KEY : TOTAL_COUNT_KEY + end + + def public_only? + !user_is_at_least_reporter? + end + + def user_is_at_least_reporter? + strong_memoize(:user_is_at_least_reporter) do + group.member?(user, Gitlab::Access::REPORTER) + end + end + + def relation_for_count + IssuesFinder.new(user, group_id: group.id, state: 'opened', non_archived: true, include_subgroups: true, public_only: public_only?).execute + end + end +end |