File: unlock_pipelines_in_queue_worker_spec.rb

package info (click to toggle)
gitlab 17.6.5-19
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 629,368 kB
  • sloc: ruby: 1,915,304; javascript: 557,307; sql: 60,639; xml: 6,509; sh: 4,567; makefile: 1,239; python: 406
file content (145 lines) | stat: -rw-r--r-- 4,742 bytes parent folder | download
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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# frozen_string_literal: true

require 'spec_helper'

RSpec.describe Ci::UnlockPipelinesInQueueWorker, :unlock_pipelines, :clean_gitlab_redis_shared_state, feature_category: :job_artifacts do
  let(:worker) { described_class.new }

  it 'is a limited capacity worker' do
    expect(described_class.new).to be_a(LimitedCapacity::Worker)
  end

  describe '#perform_work' do
    let(:service) { instance_double('Ci::UnlockPipelineService') }

    it 'pops the oldest pipeline ID from the queue and unlocks it' do
      pipeline_1 = create(:ci_pipeline, :artifacts_locked)
      pipeline_2 = create(:ci_pipeline, :artifacts_locked)

      enqueue_timestamp = nil
      travel_to(3.minutes.ago) do
        enqueue_timestamp = Time.current.utc.to_i
        Ci::UnlockPipelineRequest.enqueue(pipeline_1.id)
      end

      Ci::UnlockPipelineRequest.enqueue(pipeline_2.id)

      expect(Ci::UnlockPipelineService).to receive(:new).with(pipeline_1).and_return(service)
      expect(service)
        .to receive(:execute)
        .and_return(
          status: :success,
          skipped_already_leased: false,
          skipped_already_unlocked: false,
          exec_timeout: false,
          unlocked_job_artifacts: 3,
          unlocked_pipeline_artifacts: 2
        )

      expect(worker).to receive(:log_extra_metadata_on_done).with(:pipeline_id, pipeline_1.id)
      expect(worker).to receive(:log_extra_metadata_on_done).with(:project, pipeline_1.project.full_path)

      unlock_timestamp = Time.current.utc
      unlock_wait_time = unlock_timestamp.to_i - enqueue_timestamp
      expect(worker).to receive(:log_extra_metadata_on_done).with(:unlock_wait_time, unlock_wait_time)
      expect(worker).to receive(:log_extra_metadata_on_done).with(:remaining_pending, 1)
      expect(worker).to receive(:log_extra_metadata_on_done).with(:skipped_already_leased, false)
      expect(worker).to receive(:log_extra_metadata_on_done).with(:skipped_already_unlocked, false)
      expect(worker).to receive(:log_extra_metadata_on_done).with(:exec_timeout, false)
      expect(worker).to receive(:log_extra_metadata_on_done).with(:unlocked_job_artifacts, 3)
      expect(worker).to receive(:log_extra_metadata_on_done).with(:unlocked_pipeline_artifacts, 2)

      travel_to(unlock_timestamp) do
        expect { worker.perform_work }
          .to change { pipeline_ids_waiting_to_be_unlocked }
          .from([pipeline_1.id, pipeline_2.id])
          .to([pipeline_2.id])
      end
    end

    context 'when queue is empty' do
      it 'does nothing but still logs information' do
        expect(Ci::UnlockPipelineService).not_to receive(:new)
        expect(worker).to receive(:log_extra_metadata_on_done).with(:remaining_pending, 0)

        worker.perform_work
      end
    end

    context 'when pipeline ID does not exist' do
      before do
        Ci::UnlockPipelineRequest.enqueue(9999)
      end

      it 'does nothing' do
        expect(Ci::UnlockPipelineService).not_to receive(:new)
        expect(worker).not_to receive(:log_extra_metadata_on_done)

        worker.perform_work
      end
    end
  end

  describe '#remaining_work_count' do
    subject { worker.remaining_work_count }

    context 'and there are remaining unlock pipeline requests' do
      before do
        Ci::UnlockPipelineRequest.enqueue(123)
      end

      it { is_expected.to eq(1) }
    end

    context 'and there are no remaining unlock pipeline requests' do
      it { is_expected.to eq(0) }
    end
  end

  describe '#max_running_jobs' do
    subject { worker.max_running_jobs }

    before do
      stub_feature_flags(
        ci_unlock_pipelines_extra_low: false,
        ci_unlock_pipelines: false,
        ci_unlock_pipelines_medium: false,
        ci_unlock_pipelines_high: false
      )
    end

    it { is_expected.to eq(0) }

    context 'when ci_unlock_pipelines_extra_low flag is enabled' do
      before do
        stub_feature_flags(ci_unlock_pipelines_extra_low: true)
      end

      it { is_expected.to eq(described_class::MAX_RUNNING_EXTRA_LOW) }
    end

    context 'when ci_unlock_pipelines flag is enabled' do
      before do
        stub_feature_flags(ci_unlock_pipelines: true)
      end

      it { is_expected.to eq(described_class::MAX_RUNNING_LOW) }
    end

    context 'when ci_unlock_pipelines_medium flag is enabled' do
      before do
        stub_feature_flags(ci_unlock_pipelines_medium: true)
      end

      it { is_expected.to eq(described_class::MAX_RUNNING_MEDIUM) }
    end

    context 'when ci_unlock_pipelines_high flag is enabled' do
      before do
        stub_feature_flags(ci_unlock_pipelines_high: true)
      end

      it { is_expected.to eq(described_class::MAX_RUNNING_HIGH) }
    end
  end
end