summaryrefslogtreecommitdiff
path: root/spec/lib/gitlab/cluster/lifecycle_events_spec.rb
blob: 5eea78acd98cc5e996bac5473116968707ce2884 (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
# frozen_string_literal: true

require 'spec_helper'

RSpec.describe Gitlab::Cluster::LifecycleEvents do
  # we create a new instance to ensure that we do not touch existing hooks
  let(:replica) { Class.new(described_class) }

  context 'hooks execution' do
    using RSpec::Parameterized::TableSyntax

    where(:method, :hook_names) do
      :do_worker_start             | %i[worker_start_hooks]
      :do_before_fork              | %i[before_fork_hooks]
      :do_before_graceful_shutdown | %i[master_blackout_period master_graceful_shutdown]
      :do_before_master_restart    | %i[master_restart_hooks]
    end

    before do
      # disable blackout period to speed-up tests
      stub_config(shutdown: { blackout_seconds: 0 })
    end

    with_them do
      subject { replica.public_send(method) }

      it 'executes all hooks' do
        hook_names.each do |hook_name|
          hook = double
          replica.instance_variable_set(:"@#{hook_name}", [hook])

          # ensure that proper hooks are called
          expect(hook).to receive(:call)
          expect(replica).to receive(:call).with(hook_name, anything).and_call_original
        end

        subject
      end
    end
  end

  describe '#call' do
    let(:name) { :my_hooks }

    subject { replica.send(:call, name, hooks) }

    context 'when many hooks raise exception' do
      let(:hooks) do
        [
          -> { raise 'Exception A' },
          -> { raise 'Exception B' }
        ]
      end

      context 'USE_FATAL_LIFECYCLE_EVENTS is set to default' do
        it 'only first hook is executed and is fatal' do
          expect(hooks[0]).to receive(:call).and_call_original
          expect(hooks[1]).not_to receive(:call)

          expect(Gitlab::ErrorTracking).to receive(:track_exception).and_call_original
          expect(replica).to receive(:warn).with('ERROR: The hook my_hooks failed with exception (RuntimeError) "Exception A".')

          expect { subject }.to raise_error(described_class::FatalError, 'Exception A')
        end
      end

      context 'when USE_FATAL_LIFECYCLE_EVENTS is disabled' do
        before do
          stub_const('Gitlab::Cluster::LifecycleEvents::USE_FATAL_LIFECYCLE_EVENTS', false)
        end

        it 'many hooks are executed and all exceptions are logged' do
          expect(hooks[0]).to receive(:call).and_call_original
          expect(hooks[1]).to receive(:call).and_call_original

          expect(Gitlab::ErrorTracking).to receive(:track_exception).twice.and_call_original
          expect(replica).to receive(:warn).twice.and_call_original

          expect { subject }.not_to raise_error
        end
      end
    end
  end
end