Commit c96409cf authored by Bob Van Landuyt's avatar Bob Van Landuyt

Merge branch '267546-limited-worker-nonloopless-inner-class' into 'master'

Add an inner class in the cleanup container repository worker [RUN ALL RSPEC] [RUN AS-IF-FOSS]

See merge request gitlab-org/gitlab!56989
parents 083f3824 2c3e5971
...@@ -21,6 +21,87 @@ module ContainerExpirationPolicies ...@@ -21,6 +21,87 @@ module ContainerExpirationPolicies
cleanup_tags_service_deleted_size cleanup_tags_service_deleted_size
].freeze ].freeze
delegate :perform_work, :remaining_work_count, to: :inner_instance
def inner_instance
strong_memoize(:inner_instance) do
if loopless_enabled?
Loopless.new(self)
else
Looping.new(self)
end
end
end
def max_running_jobs
return 0 unless throttling_enabled?
::Gitlab::CurrentSettings.container_registry_expiration_policies_worker_capacity
end
def throttling_enabled?
Feature.enabled?(:container_registry_expiration_policies_throttling)
end
def loopless_enabled?
Feature.enabled?(:container_registry_expiration_policies_loopless)
end
def max_cleanup_execution_time
::Gitlab::CurrentSettings.container_registry_delete_tags_service_timeout
end
def log_info(extra_structure)
logger.info(structured_payload(extra_structure))
end
def log_on_done(result)
LOG_ON_DONE_FIELDS.each do |field|
value = result.payload[field]
next if value.nil?
log_extra_metadata_on_done(field, value)
end
before_truncate_size = result.payload[:cleanup_tags_service_before_truncate_size]
after_truncate_size = result.payload[:cleanup_tags_service_after_truncate_size]
truncated = before_truncate_size &&
after_truncate_size &&
before_truncate_size != after_truncate_size
log_extra_metadata_on_done(:cleanup_tags_service_truncated, !!truncated)
log_extra_metadata_on_done(:running_jobs_count, running_jobs_count)
end
# rubocop: disable Scalability/IdempotentWorker
# TODO: move the logic from this class to the parent one when container_registry_expiration_policies_loopless is removed
# Tracking issue: https://gitlab.com/gitlab-org/gitlab/-/issues/325273
class Loopless
# TODO fill the logic here with the approach documented in
# https://gitlab.com/gitlab-org/gitlab/-/issues/267546#limited-worker
def initialize(parent)
@parent = parent
end
end
# rubocop: enable Scalability/IdempotentWorker
# rubocop: disable Scalability/IdempotentWorker
# TODO remove this class when `container_registry_expiration_policies_loopless` is removed
# Tracking issue: https://gitlab.com/gitlab-org/gitlab/-/issues/325273
class Looping
include Gitlab::Utils::StrongMemoize
delegate :throttling_enabled?,
:log_extra_metadata_on_done,
:log_info,
:log_on_done,
:max_cleanup_execution_time,
to: :@parent
def initialize(parent)
@parent = parent
end
def perform_work def perform_work
return unless throttling_enabled? return unless throttling_enabled?
return unless container_repository return unless container_repository
...@@ -53,12 +134,6 @@ module ContainerExpirationPolicies ...@@ -53,12 +134,6 @@ module ContainerExpirationPolicies
total_count total_count
end end
def max_running_jobs
return 0 unless throttling_enabled?
::Gitlab::CurrentSettings.current_application_settings.container_registry_expiration_policies_worker_capacity
end
private private
def allowed_to_run?(container_repository) def allowed_to_run?(container_repository)
...@@ -67,14 +142,6 @@ module ContainerExpirationPolicies ...@@ -67,14 +142,6 @@ module ContainerExpirationPolicies
Time.zone.now + max_cleanup_execution_time.seconds < policy.next_run_at Time.zone.now + max_cleanup_execution_time.seconds < policy.next_run_at
end end
def throttling_enabled?
Feature.enabled?(:container_registry_expiration_policies_throttling)
end
def max_cleanup_execution_time
::Gitlab::CurrentSettings.current_application_settings.container_registry_delete_tags_service_timeout
end
def policy def policy
project.container_expiration_policy project.container_expiration_policy
end end
...@@ -98,27 +165,7 @@ module ContainerExpirationPolicies ...@@ -98,27 +165,7 @@ module ContainerExpirationPolicies
end end
end end
end end
def log_info(extra_structure)
logger.info(structured_payload(extra_structure))
end
def log_on_done(result)
LOG_ON_DONE_FIELDS.each do |field|
value = result.payload[field]
next if value.nil?
log_extra_metadata_on_done(field, value)
end
before_truncate_size = result.payload[:cleanup_tags_service_before_truncate_size]
after_truncate_size = result.payload[:cleanup_tags_service_after_truncate_size]
truncated = before_truncate_size &&
after_truncate_size &&
before_truncate_size != after_truncate_size
log_extra_metadata_on_done(:cleanup_tags_service_truncated, !!truncated)
log_extra_metadata_on_done(:running_jobs_count, running_jobs_count)
end end
# rubocop: enable Scalability/IdempotentWorker
end end
end end
...@@ -106,6 +106,11 @@ RSpec.describe ContainerExpirationPolicies::CleanupContainerRepositoryWorker do ...@@ -106,6 +106,11 @@ RSpec.describe ContainerExpirationPolicies::CleanupContainerRepositoryWorker do
end end
end end
context 'with loopless disabled' do
before do
stub_feature_flags(container_registry_expiration_policies_loopless: false)
end
context 'with repository in cleanup scheduled state' do context 'with repository in cleanup scheduled state' do
it_behaves_like 'handling all repository conditions' it_behaves_like 'handling all repository conditions'
end end
...@@ -198,6 +203,7 @@ RSpec.describe ContainerExpirationPolicies::CleanupContainerRepositoryWorker do ...@@ -198,6 +203,7 @@ RSpec.describe ContainerExpirationPolicies::CleanupContainerRepositoryWorker do
expect { subject }.not_to change { ContainerRepository.waiting_for_cleanup.count } expect { subject }.not_to change { ContainerRepository.waiting_for_cleanup.count }
end end
end end
end
def cleanup_service_response(status: :finished, repository:, cleanup_tags_service_original_size: 100, cleanup_tags_service_before_truncate_size: 80, cleanup_tags_service_after_truncate_size: 80, cleanup_tags_service_before_delete_size: 50, cleanup_tags_service_deleted_size: 50) def cleanup_service_response(status: :finished, repository:, cleanup_tags_service_original_size: 100, cleanup_tags_service_before_truncate_size: 80, cleanup_tags_service_after_truncate_size: 80, cleanup_tags_service_before_delete_size: 50, cleanup_tags_service_deleted_size: 50)
ServiceResponse.success( ServiceResponse.success(
...@@ -230,6 +236,10 @@ RSpec.describe ContainerExpirationPolicies::CleanupContainerRepositoryWorker do ...@@ -230,6 +236,10 @@ RSpec.describe ContainerExpirationPolicies::CleanupContainerRepositoryWorker do
describe '#remaining_work_count' do describe '#remaining_work_count' do
subject { worker.remaining_work_count } subject { worker.remaining_work_count }
context 'with loopless disabled' do
before do
stub_feature_flags(container_registry_expiration_policies_loopless: false)
end
context 'with container repositoires waiting for cleanup' do context 'with container repositoires waiting for cleanup' do
let_it_be(:unfinished_repositories) { create_list(:container_repository, 2, :cleanup_unfinished) } let_it_be(:unfinished_repositories) { create_list(:container_repository, 2, :cleanup_unfinished) }
...@@ -264,6 +274,7 @@ RSpec.describe ContainerExpirationPolicies::CleanupContainerRepositoryWorker do ...@@ -264,6 +274,7 @@ RSpec.describe ContainerExpirationPolicies::CleanupContainerRepositoryWorker do
end end
end end
end end
end
describe '#max_running_jobs' do describe '#max_running_jobs' do
let(:capacity) { 50 } let(:capacity) { 50 }
...@@ -274,6 +285,11 @@ RSpec.describe ContainerExpirationPolicies::CleanupContainerRepositoryWorker do ...@@ -274,6 +285,11 @@ RSpec.describe ContainerExpirationPolicies::CleanupContainerRepositoryWorker do
stub_application_setting(container_registry_expiration_policies_worker_capacity: capacity) stub_application_setting(container_registry_expiration_policies_worker_capacity: capacity)
end end
context 'with loopless disabled' do
before do
stub_feature_flags(container_registry_expiration_policies_loopless: false)
end
it { is_expected.to eq(capacity) } it { is_expected.to eq(capacity) }
context 'with feature flag disabled' do context 'with feature flag disabled' do
...@@ -284,6 +300,7 @@ RSpec.describe ContainerExpirationPolicies::CleanupContainerRepositoryWorker do ...@@ -284,6 +300,7 @@ RSpec.describe ContainerExpirationPolicies::CleanupContainerRepositoryWorker do
it { is_expected.to eq(0) } it { is_expected.to eq(0) }
end end
end end
end
def expect_log_info(structure) def expect_log_info(structure)
expect(worker.logger) expect(worker.logger)
......
...@@ -35,12 +35,18 @@ RSpec.describe ContainerExpirationPolicyWorker do ...@@ -35,12 +35,18 @@ RSpec.describe ContainerExpirationPolicyWorker do
end end
context 'With no container expiration policies' do context 'With no container expiration policies' do
context 'with loopless disabled' do
before do
stub_feature_flags(container_registry_expiration_policies_loopless: false)
end
it 'does not execute any policies' do it 'does not execute any policies' do
expect(ContainerRepository).not_to receive(:for_project_id) expect(ContainerRepository).not_to receive(:for_project_id)
expect { subject }.not_to change { ContainerRepository.cleanup_scheduled.count } expect { subject }.not_to change { ContainerRepository.cleanup_scheduled.count }
end end
end end
end
context 'with throttling enabled' do context 'with throttling enabled' do
before do before 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