diff options
Diffstat (limited to 'app/workers/container_registry/delete_container_repository_worker.rb')
-rw-r--r-- | app/workers/container_registry/delete_container_repository_worker.rb | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/app/workers/container_registry/delete_container_repository_worker.rb b/app/workers/container_registry/delete_container_repository_worker.rb new file mode 100644 index 00000000000..1f94b1b9e71 --- /dev/null +++ b/app/workers/container_registry/delete_container_repository_worker.rb @@ -0,0 +1,81 @@ +# frozen_string_literal: true + +module ContainerRegistry + class DeleteContainerRepositoryWorker + include ApplicationWorker + include LimitedCapacity::Worker + include Gitlab::Utils::StrongMemoize + extend ::Gitlab::Utils::Override + + data_consistency :always + queue_namespace :container_repository_delete + feature_category :container_registry + urgency :low + worker_resource_boundary :unknown + idempotent! + + MAX_CAPACITY = 2 + CLEANUP_TAGS_SERVICE_PARAMS = { + 'name_regex_delete' => '.*', + 'container_expiration_policy' => true # to avoid permissions checks + }.freeze + + def perform_work + return unless next_container_repository + + result = delete_tags + log_delete_tags_service_result(next_container_repository, result) + + if result[:status] == :error || next_container_repository.tags_count != 0 + return next_container_repository.set_delete_scheduled_status + end + + next_container_repository.destroy! + rescue StandardError => exception + next_container_repository&.set_delete_scheduled_status + + Gitlab::ErrorTracking.log_exception(exception, class: self.class.name) + end + + def remaining_work_count + ::ContainerRepository.delete_scheduled.limit(max_running_jobs + 1).count + end + + def max_running_jobs + MAX_CAPACITY + end + + private + + def delete_tags + service = Projects::ContainerRepository::CleanupTagsService.new( + container_repository: next_container_repository, + params: CLEANUP_TAGS_SERVICE_PARAMS + ) + service.execute + end + + def next_container_repository + strong_memoize(:next_container_repository) do + ContainerRepository.transaction do + # we don't care about the order + repository = ContainerRepository.next_pending_destruction(order_by: nil) + + repository&.tap(&:set_delete_ongoing_status) + end + end + end + + def log_delete_tags_service_result(container_repository, delete_tags_service_result) + logger.info( + structured_payload( + project_id: container_repository.project_id, + container_repository_id: container_repository.id, + container_repository_path: container_repository.path, + tags_size_before_delete: delete_tags_service_result[:original_size], + deleted_tags_size: delete_tags_service_result[:deleted_size] + ) + ) + end + end +end |