Pipeline canceling technical debts
From: #21098 (comment 544960059)
The method Ci::Pipeline#cancel_running
method is too complicated and it should be in a service. I'll look into it in future works =>
Future work drafts:
- Find all methods calling cancel_running
- TODO: Ci::BuildRunnerSession.where(build: build).delete_all
- TODO: validate :name_uniqueness_across_types, unless: :importing?
- TODO: Try to have only one UPDATE SQL query
moving to a service
# rubocop: disable CodeReuse/ServiceClass
def cancel_running(retries: nil, &block)
Ci::CancelPipelineService.new.execute(self, retries, block)
end
# rubocop: enable CodeReuse/ServiceClass
# frozen_string_literal: true
module Ci
class CancelPipelineService
COMMIT_STATUS_RELATIONS = %i(project, pipeline)
CI_BUILD_RELATIONS = %i(deployment, taggings)
# rubocop: disable CodeReuse/ActiveRecord
def execute(pipeline, max_retries, &block)
Gitlab::OptimisticLocking.retry_lock(pipeline.cancelable_statuses, max_retries, name: 'ci_pipeline_cancel_running') do |cancelables|
cancelables.find_in_batches do |batch|
ActiveRecord::Associations::Preloader.new.preload(batch, COMMIT_STATUS_RELATIONS)
ActiveRecord::Associations::Preloader.new.preload(batch.select { |job| job.is_a?(Ci::Build) }, CI_BUILD_RELATIONS)
batch.each do |job|
yield(job) if block
job.cancel
end
end
end
end
# rubocop: enable CodeReuse/ActiveRecord
end
end