summaryrefslogtreecommitdiff
path: root/lib/gitlab/ci/pipeline/chain/cancel_pending_pipelines.rb
blob: f637001f9f8c05cd86dbafe56c45f7e6b5b98e41 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# frozen_string_literal: true

module Gitlab
  module Ci
    module Pipeline
      module Chain
        class CancelPendingPipelines < Chain::Base
          include Chain::Helpers

          BATCH_SIZE = 25

          # rubocop: disable CodeReuse/ActiveRecord
          def perform!
            return unless project.auto_cancel_pending_pipelines?

            Gitlab::OptimisticLocking.retry_lock(auto_cancelable_pipelines, name: 'cancel_pending_pipelines') do |cancelables|
              cancelables.select(:id).each_batch(of: BATCH_SIZE) do |cancelables_batch|
                auto_cancel_interruptible_pipelines(cancelables_batch.ids)
              end
            end
          end
          # rubocop: enable CodeReuse/ActiveRecord

          def break?
            false
          end

          private

          def auto_cancelable_pipelines
            project.all_pipelines.created_after(1.week.ago)
              .ci_and_parent_sources
              .for_ref(pipeline.ref)
              .id_not_in(pipeline.same_family_pipeline_ids)
              .where_not_sha(project.commit(pipeline.ref).try(:id))
              .alive_or_scheduled
          end

          def auto_cancel_interruptible_pipelines(pipeline_ids)
            ::Ci::Pipeline
              .id_in(pipeline_ids)
              .with_only_interruptible_builds
              .each { |cancelable| cancelable.auto_cancel_running(pipeline) }
          end
        end
      end
    end
  end
end