Welcome to mirror list, hosted at ThFree Co, Russian Federation.

sidekiq_cluster_spec.rb « sidekiq_cluster « spec - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 86b3fc6a48c1e6c851e2a2a65c9a2d50198ae11d (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
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
# frozen_string_literal: true

require 'rspec-parameterized'

require_relative '../../sidekiq_cluster/sidekiq_cluster'

RSpec.describe Gitlab::SidekiqCluster do # rubocop:disable RSpec/FilePath
  describe '.start' do
    it 'starts Sidekiq with the given queues, environment and options' do
      process_options = {
        pgroup: true,
        err: $stderr,
        out: $stdout
      }

      expect(Process).to receive(:spawn).ordered.with({
          "ENABLE_SIDEKIQ_CLUSTER" => "1",
          "SIDEKIQ_WORKER_ID" => "0"
        },
        "bundle", "exec", "sidekiq", "-c10", "-eproduction", "-t25", "-gqueues:foo", "-rfoo/bar", "-qfoo,1", process_options
      )
      expect(Process).to receive(:spawn).ordered.with({
        "ENABLE_SIDEKIQ_CLUSTER" => "1",
        "SIDEKIQ_WORKER_ID" => "1"
        },
        "bundle", "exec", "sidekiq", "-c10", "-eproduction", "-t25", "-gqueues:bar,baz", "-rfoo/bar", "-qbar,1", "-qbaz,1", process_options
      )

      described_class.start([%w(foo), %w(bar baz)], env: :production, directory: 'foo/bar', max_concurrency: 20, min_concurrency: 10)
    end

    it 'starts Sidekiq with the given queues and sensible default options' do
      expected_options = {
        env: :development,
        directory: an_instance_of(String),
        max_concurrency: 50,
        min_concurrency: 0,
        worker_id: an_instance_of(Integer),
        timeout: 25,
        dryrun: false
      }

      expect(described_class).to receive(:start_sidekiq).ordered.with(%w(foo bar baz), expected_options)
      expect(described_class).to receive(:start_sidekiq).ordered.with(%w(solo), expected_options)

      described_class.start([%w(foo bar baz), %w(solo)])
    end
  end

  describe '.start_sidekiq' do
    let(:first_worker_id) { 0 }
    let(:options) do
      { env: :production, directory: 'foo/bar', max_concurrency: 20, min_concurrency: 0, worker_id: first_worker_id, timeout: 10, dryrun: false }
    end

    let(:env) { { "ENABLE_SIDEKIQ_CLUSTER" => "1", "SIDEKIQ_WORKER_ID" => first_worker_id.to_s } }
    let(:args) { ['bundle', 'exec', 'sidekiq', anything, '-eproduction', '-t10', *([anything] * 5)] }

    it 'starts a Sidekiq process' do
      allow(Process).to receive(:spawn).and_return(1)

      expect(Gitlab::ProcessManagement).to receive(:wait_async).with(1)
      expect(described_class.start_sidekiq(%w(foo), **options)).to eq(1)
    end

    it 'handles duplicate queue names' do
      allow(Process)
        .to receive(:spawn)
        .with(env, *args, anything)
        .and_return(1)

      expect(Gitlab::ProcessManagement).to receive(:wait_async).with(1)
      expect(described_class.start_sidekiq(%w(foo foo bar baz), **options)).to eq(1)
    end

    it 'runs the sidekiq process in a new process group' do
      expect(Process)
        .to receive(:spawn)
        .with(anything, *args, a_hash_including(pgroup: true))
        .and_return(1)

      allow(Gitlab::ProcessManagement).to receive(:wait_async)
      expect(described_class.start_sidekiq(%w(foo bar baz), **options)).to eq(1)
    end
  end

  describe '.count_by_queue' do
    it 'tallies the queue counts' do
      queues = [%w(foo), %w(bar baz), %w(foo)]

      expect(described_class.count_by_queue(queues)).to eq(%w(foo) => 2, %w(bar baz) => 1)
    end
  end

  describe '.concurrency' do
    using RSpec::Parameterized::TableSyntax

    where(:queue_count, :min, :max, :expected) do
      2 | 0 | 0 | 3 # No min or max specified
      2 | 0 | 9 | 3 # No min specified, value < max
      2 | 1 | 4 | 3 # Value between min and max
      2 | 4 | 5 | 4 # Value below range
      5 | 2 | 3 | 3 # Value above range
      2 | 1 | 1 | 1 # Value above explicit setting (min == max)
      0 | 3 | 3 | 3 # Value below explicit setting (min == max)
      1 | 4 | 3 | 3 # Min greater than max
    end

    with_them do
      let(:queues) { Array.new(queue_count) }

      it { expect(described_class.concurrency(queues, min, max)).to eq(expected) }
    end
  end
end