stoplight 4.1.0 → 5.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +289 -350
- data/lib/stoplight/admin/actions/action.rb +24 -0
- data/lib/stoplight/admin/actions/lock.rb +23 -0
- data/lib/stoplight/admin/actions/lock_all_green.rb +18 -0
- data/lib/stoplight/admin/actions/lock_green.rb +23 -0
- data/lib/stoplight/admin/actions/lock_red.rb +23 -0
- data/lib/stoplight/admin/actions/stats.rb +27 -0
- data/lib/stoplight/admin/actions/unlock.rb +23 -0
- data/lib/stoplight/admin/dependencies.rb +50 -0
- data/lib/stoplight/admin/helpers.rb +27 -0
- data/lib/stoplight/admin/lights_repository/light.rb +155 -0
- data/lib/stoplight/admin/lights_repository.rb +74 -0
- data/lib/stoplight/admin/lights_stats.rb +77 -0
- data/lib/stoplight/admin/views/_card.erb +120 -0
- data/lib/stoplight/admin/views/index.erb +36 -0
- data/lib/stoplight/admin/views/layout.erb +66 -0
- data/lib/stoplight/admin.rb +68 -0
- data/lib/stoplight/color.rb +3 -3
- data/lib/stoplight/config/config_provider.rb +62 -0
- data/lib/stoplight/config/library_default_config.rb +29 -0
- data/lib/stoplight/config/user_default_config.rb +83 -0
- data/lib/stoplight/data_store/base.rb +59 -33
- data/lib/stoplight/data_store/fail_safe.rb +105 -0
- data/lib/stoplight/data_store/memory.rb +257 -50
- data/lib/stoplight/data_store/redis/get_metadata.lua +38 -0
- data/lib/stoplight/data_store/redis/lua.rb +23 -0
- data/lib/stoplight/data_store/redis/record_failure.lua +36 -0
- data/lib/stoplight/data_store/redis/record_success.lua +35 -0
- data/lib/stoplight/data_store/redis/transition_to_green.lua +10 -0
- data/lib/stoplight/data_store/redis/transition_to_red.lua +10 -0
- data/lib/stoplight/data_store/redis/transition_to_yellow.lua +9 -0
- data/lib/stoplight/data_store/redis.rb +345 -106
- data/lib/stoplight/default.rb +11 -9
- data/lib/stoplight/error.rb +1 -13
- data/lib/stoplight/failure.rb +14 -13
- data/lib/stoplight/light/config.rb +118 -0
- data/lib/stoplight/light/configuration_builder_interface.rb +128 -0
- data/lib/stoplight/light/green_run_strategy.rb +53 -0
- data/lib/stoplight/light/red_run_strategy.rb +26 -0
- data/lib/stoplight/light/run_strategy.rb +30 -0
- data/lib/stoplight/light/yellow_run_strategy.rb +78 -0
- data/lib/stoplight/light.rb +164 -84
- data/lib/stoplight/metadata.rb +71 -0
- data/lib/stoplight/notifier/base.rb +14 -7
- data/lib/stoplight/notifier/fail_safe.rb +67 -0
- data/lib/stoplight/notifier/generic.rb +54 -5
- data/lib/stoplight/rspec/generic_notifier.rb +11 -12
- data/lib/stoplight/rspec.rb +1 -1
- data/lib/stoplight/state.rb +3 -3
- data/lib/stoplight/traffic_control/base.rb +35 -0
- data/lib/stoplight/traffic_control/consecutive_failures.rb +43 -0
- data/lib/stoplight/traffic_recovery/base.rb +51 -0
- data/lib/stoplight/traffic_recovery/single_success.rb +35 -0
- data/lib/stoplight/version.rb +1 -1
- data/lib/stoplight.rb +111 -51
- metadata +49 -98
- data/lib/stoplight/builder.rb +0 -70
- data/lib/stoplight/circuit_breaker.rb +0 -102
- data/lib/stoplight/configurable.rb +0 -95
- data/lib/stoplight/configuration.rb +0 -126
- data/lib/stoplight/light/deprecated.rb +0 -44
- data/lib/stoplight/light/lockable.rb +0 -45
- data/lib/stoplight/light/runnable.rb +0 -127
- data/lib/stoplight/notifier.rb +0 -6
- data/spec/spec_helper.rb +0 -22
- data/spec/stoplight/builder_spec.rb +0 -165
- data/spec/stoplight/circuit_breaker_spec.rb +0 -43
- data/spec/stoplight/color_spec.rb +0 -39
- data/spec/stoplight/configurable_spec.rb +0 -25
- data/spec/stoplight/data_store/base_spec.rb +0 -71
- data/spec/stoplight/data_store/memory_spec.rb +0 -22
- data/spec/stoplight/data_store/redis_spec.rb +0 -45
- data/spec/stoplight/data_store_spec.rb +0 -9
- data/spec/stoplight/default_spec.rb +0 -80
- data/spec/stoplight/error_spec.rb +0 -39
- data/spec/stoplight/failure_spec.rb +0 -108
- data/spec/stoplight/light/lockable_spec.rb +0 -93
- data/spec/stoplight/light/runnable_spec.rb +0 -38
- data/spec/stoplight/light_spec.rb +0 -156
- data/spec/stoplight/notifier/base_spec.rb +0 -18
- data/spec/stoplight/notifier/generic_spec.rb +0 -50
- data/spec/stoplight/notifier/io_spec.rb +0 -41
- data/spec/stoplight/notifier/logger_spec.rb +0 -75
- data/spec/stoplight/notifier_spec.rb +0 -9
- data/spec/stoplight/state_spec.rb +0 -39
- data/spec/stoplight/version_spec.rb +0 -9
- data/spec/stoplight_spec.rb +0 -32
- data/spec/support/configurable.rb +0 -69
- data/spec/support/data_store/base/clear_failures.rb +0 -18
- data/spec/support/data_store/base/clear_state.rb +0 -20
- data/spec/support/data_store/base/get_all.rb +0 -44
- data/spec/support/data_store/base/get_failures.rb +0 -30
- data/spec/support/data_store/base/get_state.rb +0 -7
- data/spec/support/data_store/base/names.rb +0 -29
- data/spec/support/data_store/base/record_failures.rb +0 -70
- data/spec/support/data_store/base/set_state.rb +0 -15
- data/spec/support/data_store/base/with_notification_lock.rb +0 -27
- data/spec/support/data_store/base.rb +0 -21
- data/spec/support/database_cleaner.rb +0 -26
- data/spec/support/exception_helpers.rb +0 -9
- data/spec/support/light/runnable/color.rb +0 -79
- data/spec/support/light/runnable/run.rb +0 -247
- data/spec/support/light/runnable/state.rb +0 -31
- data/spec/support/light/runnable.rb +0 -5
@@ -1,156 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
require 'stringio'
|
5
|
-
|
6
|
-
RSpec.describe Stoplight::Light do
|
7
|
-
let(:light) { described_class.new(name, &code) }
|
8
|
-
let(:name) { ('a'..'z').to_a.shuffle.join }
|
9
|
-
let(:code) { -> {} }
|
10
|
-
|
11
|
-
it 'is a class' do
|
12
|
-
expect(described_class).to be_a(Class)
|
13
|
-
end
|
14
|
-
|
15
|
-
describe '.default_data_store' do
|
16
|
-
it 'is initially the default' do
|
17
|
-
expect(described_class.default_data_store)
|
18
|
-
.to eql(Stoplight::Default::DATA_STORE)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
describe '.default_data_store=' do
|
23
|
-
before { @default_data_store = described_class.default_data_store }
|
24
|
-
after { described_class.default_data_store = @default_data_store }
|
25
|
-
|
26
|
-
it 'sets the data store' do
|
27
|
-
data_store = Stoplight::DataStore::Memory.new
|
28
|
-
described_class.default_data_store = data_store
|
29
|
-
expect(described_class.default_data_store).to eql(data_store)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
describe '.default_error_notifier' do
|
34
|
-
it 'is initially the default' do
|
35
|
-
expect(described_class.default_error_notifier)
|
36
|
-
.to eql(Stoplight::Default::ERROR_NOTIFIER)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
describe '.default_error_notifier=' do
|
41
|
-
before { @default_error_notifier = described_class.default_error_notifier }
|
42
|
-
after { described_class.default_error_notifier = @default_error_notifier }
|
43
|
-
|
44
|
-
it 'sets the error notifier' do
|
45
|
-
default_error_notifier = ->(_) {}
|
46
|
-
described_class.default_error_notifier = default_error_notifier
|
47
|
-
expect(described_class.default_error_notifier)
|
48
|
-
.to eql(default_error_notifier)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
describe '.default_notifiers' do
|
53
|
-
it 'is initially the default' do
|
54
|
-
expect(described_class.default_notifiers)
|
55
|
-
.to eql(Stoplight::Default::NOTIFIERS)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
describe '.default_notifiers=' do
|
60
|
-
before { @default_notifiers = described_class.default_notifiers }
|
61
|
-
after { described_class.default_notifiers = @default_notifiers }
|
62
|
-
|
63
|
-
it 'sets the data store' do
|
64
|
-
notifiers = []
|
65
|
-
described_class.default_notifiers = notifiers
|
66
|
-
expect(described_class.default_notifiers).to eql(notifiers)
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
describe '#code' do
|
71
|
-
it 'reads the code' do
|
72
|
-
expect(light.code).to eql(code)
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
describe '#cool_off_time' do
|
77
|
-
it 'is initially the default' do
|
78
|
-
expect(light.cool_off_time).to eql(Stoplight::Default::COOL_OFF_TIME)
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
describe '#data_store' do
|
83
|
-
it 'is initially the default' do
|
84
|
-
expect(light.data_store).to eql(described_class.default_data_store)
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
describe '#error_handler' do
|
89
|
-
it 'it initially the default' do
|
90
|
-
expect(light.error_handler).to eql(Stoplight::Default::ERROR_HANDLER)
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
describe '#error_notifier' do
|
95
|
-
it 'it initially the default' do
|
96
|
-
expect(light.error_notifier)
|
97
|
-
.to eql(described_class.default_error_notifier)
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
describe '#fallback' do
|
102
|
-
it 'is initially the default' do
|
103
|
-
expect(light.fallback).to eql(Stoplight::Default::FALLBACK)
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
describe '#name' do
|
108
|
-
it 'reads the name' do
|
109
|
-
expect(light.name).to eql(name)
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
describe '#notifiers' do
|
114
|
-
it 'is initially the default' do
|
115
|
-
expect(light.notifiers).to eql(described_class.default_notifiers)
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
describe '#threshold' do
|
120
|
-
it 'is initially the default' do
|
121
|
-
expect(light.threshold).to eql(Stoplight::Default::THRESHOLD)
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
describe '#window_size' do
|
126
|
-
it 'is initially the default' do
|
127
|
-
expect(light.window_size).to eql(Stoplight::Default::WINDOW_SIZE)
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
describe '#with_error_handler' do
|
132
|
-
it 'sets the error handler' do
|
133
|
-
error_handler = ->(_, _) {}
|
134
|
-
light.with_error_handler(&error_handler)
|
135
|
-
expect(light.error_handler).to eql(error_handler)
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
describe '#with_error_notifier' do
|
140
|
-
it 'sets the error notifier' do
|
141
|
-
error_notifier = ->(_) {}
|
142
|
-
light.with_error_notifier(&error_notifier)
|
143
|
-
expect(light.error_notifier).to eql(error_notifier)
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
describe '#with_fallback' do
|
148
|
-
it 'sets the fallback' do
|
149
|
-
fallback = ->(_) {}
|
150
|
-
light.with_fallback(&fallback)
|
151
|
-
expect(light.fallback).to eql(fallback)
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
it_behaves_like Stoplight::Configurable
|
156
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
RSpec.describe Stoplight::Notifier::Base do
|
6
|
-
let(:notifier) { described_class.new }
|
7
|
-
|
8
|
-
it 'is a class' do
|
9
|
-
expect(described_class).to be_a(Class)
|
10
|
-
end
|
11
|
-
|
12
|
-
describe '#notify' do
|
13
|
-
it 'is not implemented' do
|
14
|
-
expect { notifier.notify(nil, nil, nil, nil) }
|
15
|
-
.to raise_error(NotImplementedError)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
@@ -1,50 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
RSpec.describe Stoplight::Notifier::Generic do
|
6
|
-
let(:light) { Stoplight::Light.new(name) {} }
|
7
|
-
let(:name) { ('a'..'z').to_a.shuffle.join }
|
8
|
-
let(:from_color) { Stoplight::Color::GREEN }
|
9
|
-
let(:to_color) { Stoplight::Color::RED }
|
10
|
-
let(:error) { nil }
|
11
|
-
|
12
|
-
it 'is a module' do
|
13
|
-
expect(described_class).to be_a(Module)
|
14
|
-
end
|
15
|
-
|
16
|
-
describe '#put' do
|
17
|
-
let(:notifier) { notifier_class.new(double.as_null_object) }
|
18
|
-
let(:notifier_class) do
|
19
|
-
Class.new do
|
20
|
-
include Stoplight::Notifier::Generic
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
it 'has to implement the #put method' do
|
25
|
-
expect do
|
26
|
-
notifier.notify(light, from_color, to_color, error)
|
27
|
-
end.to raise_error(NotImplementedError)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
describe '#notify' do
|
32
|
-
let(:formatted_message) { 'formatted message' }
|
33
|
-
let(:notifier) { notifier_class.new(object) }
|
34
|
-
let(:notifier_class) do
|
35
|
-
Class.new do
|
36
|
-
include Stoplight::Notifier::Generic
|
37
|
-
def put(message)
|
38
|
-
object.put(message)
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
it 'puts formatted message' do
|
43
|
-
expect(formatter).to receive(:call).with(light, from_color, to_color, error) { formatted_message }
|
44
|
-
expect(object).to receive(:put).with(formatted_message)
|
45
|
-
|
46
|
-
expect(notifier.notify(light, from_color, to_color, error)).to eq(formatted_message)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
@@ -1,41 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
require 'stringio'
|
5
|
-
require 'stoplight/rspec'
|
6
|
-
|
7
|
-
RSpec.describe Stoplight::Notifier::IO do
|
8
|
-
it_behaves_like 'a generic notifier'
|
9
|
-
|
10
|
-
it 'is a class' do
|
11
|
-
expect(described_class).to be_a(Class)
|
12
|
-
end
|
13
|
-
|
14
|
-
it 'is a subclass of Base' do
|
15
|
-
expect(described_class).to be < Stoplight::Notifier::Base
|
16
|
-
end
|
17
|
-
|
18
|
-
describe '#io' do
|
19
|
-
it 'reads the IO' do
|
20
|
-
io = StringIO.new
|
21
|
-
expect(described_class.new(io).io).to eql(io)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
describe '#notify' do
|
26
|
-
let(:light) { Stoplight::Light.new(name, &code) }
|
27
|
-
let(:name) { ('a'..'z').to_a.shuffle.join }
|
28
|
-
let(:code) { -> {} }
|
29
|
-
let(:from_color) { Stoplight::Color::GREEN }
|
30
|
-
let(:to_color) { Stoplight::Color::RED }
|
31
|
-
let(:notifier) { described_class.new(io) }
|
32
|
-
let(:io) { StringIO.new }
|
33
|
-
|
34
|
-
it 'writes the message' do
|
35
|
-
error = nil
|
36
|
-
notifier.notify(light, from_color, to_color, error)
|
37
|
-
message = notifier.formatter.call(light, from_color, to_color, error)
|
38
|
-
expect(io.string).to eql("#{message}\n")
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
@@ -1,75 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
require 'logger'
|
5
|
-
require 'stringio'
|
6
|
-
require 'stoplight/rspec'
|
7
|
-
|
8
|
-
RSpec.describe Stoplight::Notifier::Logger do
|
9
|
-
it_behaves_like 'a generic notifier'
|
10
|
-
|
11
|
-
it 'is a class' do
|
12
|
-
expect(described_class).to be_a(Class)
|
13
|
-
end
|
14
|
-
|
15
|
-
it 'is a subclass of Base' do
|
16
|
-
expect(described_class).to be < Stoplight::Notifier::Base
|
17
|
-
end
|
18
|
-
|
19
|
-
describe '#formatter' do
|
20
|
-
it 'is initially the default' do
|
21
|
-
expect(described_class.new(nil, nil).formatter)
|
22
|
-
.to eql(Stoplight::Default::FORMATTER)
|
23
|
-
end
|
24
|
-
|
25
|
-
it 'reads the formatter' do
|
26
|
-
formatter = proc {}
|
27
|
-
expect(described_class.new(nil, formatter).formatter)
|
28
|
-
.to eql(formatter)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
describe '#logger' do
|
33
|
-
it 'reads the logger' do
|
34
|
-
logger = Logger.new(StringIO.new)
|
35
|
-
expect(described_class.new(logger, nil).logger)
|
36
|
-
.to eql(logger)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
describe '#notify' do
|
41
|
-
let(:light) { Stoplight::Light.new(name, &code) }
|
42
|
-
let(:name) { ('a'..'z').to_a.shuffle.join }
|
43
|
-
let(:code) { -> {} }
|
44
|
-
let(:from_color) { Stoplight::Color::GREEN }
|
45
|
-
let(:to_color) { Stoplight::Color::RED }
|
46
|
-
let(:notifier) { described_class.new(Logger.new(io)) }
|
47
|
-
let(:io) { StringIO.new }
|
48
|
-
|
49
|
-
before do
|
50
|
-
notifier.notify(light, from_color, to_color, error)
|
51
|
-
end
|
52
|
-
|
53
|
-
subject(:result) { io.string }
|
54
|
-
|
55
|
-
context 'when no error given' do
|
56
|
-
let(:error) { nil }
|
57
|
-
|
58
|
-
it 'logs message' do
|
59
|
-
expect(result).to match(/.+#{message}/)
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
context 'when message with an error given' do
|
64
|
-
let(:error) { ZeroDivisionError.new('divided by 0') }
|
65
|
-
|
66
|
-
it 'logs message' do
|
67
|
-
expect(result).to match(/.+#{message}/)
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
def message
|
72
|
-
notifier.formatter.call(light, from_color, to_color, error)
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
@@ -1,39 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
RSpec.describe Stoplight::State do
|
6
|
-
it 'is a module' do
|
7
|
-
expect(described_class).to be_a(Module)
|
8
|
-
end
|
9
|
-
|
10
|
-
describe '::UNLOCKED' do
|
11
|
-
it 'is a string' do
|
12
|
-
expect(Stoplight::State::UNLOCKED).to be_a(String)
|
13
|
-
end
|
14
|
-
|
15
|
-
it 'is frozen' do
|
16
|
-
expect(Stoplight::State::UNLOCKED).to be_frozen
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
describe '::LOCKED_GREEN' do
|
21
|
-
it 'is a string' do
|
22
|
-
expect(Stoplight::State::LOCKED_GREEN).to be_a(String)
|
23
|
-
end
|
24
|
-
|
25
|
-
it 'is frozen' do
|
26
|
-
expect(Stoplight::State::LOCKED_GREEN).to be_frozen
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
describe '::LOCKED_RED' do
|
31
|
-
it 'is a string' do
|
32
|
-
expect(Stoplight::State::LOCKED_RED).to be_a(String)
|
33
|
-
end
|
34
|
-
|
35
|
-
it 'is frozen' do
|
36
|
-
expect(Stoplight::State::LOCKED_RED).to be_frozen
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
data/spec/stoplight_spec.rb
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
RSpec.describe Stoplight do
|
6
|
-
it 'is a module' do
|
7
|
-
expect(described_class).to be_a(Module)
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
RSpec.describe 'Stoplight' do
|
12
|
-
let(:name) { ('a'..'z').to_a.shuffle.join }
|
13
|
-
|
14
|
-
context 'with code' do
|
15
|
-
subject(:light) { Stoplight(name, &code) }
|
16
|
-
let(:code) { -> {} }
|
17
|
-
|
18
|
-
it 'creates a stoplight' do
|
19
|
-
expect(light).to be_a(Stoplight::Light)
|
20
|
-
expect(light.name).to eql(name)
|
21
|
-
expect(light.code).to eql(code)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
context 'without code' do
|
26
|
-
subject(:light) { Stoplight(name) }
|
27
|
-
|
28
|
-
it 'creates a stoplight' do
|
29
|
-
expect(light).to eq(Stoplight::Builder.with(name: name))
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
@@ -1,69 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.shared_examples Stoplight::Configurable do
|
4
|
-
let(:configurable) { described_class.new(configuration) }
|
5
|
-
|
6
|
-
let(:configuration) do
|
7
|
-
Stoplight::Configuration.new(
|
8
|
-
name: name,
|
9
|
-
data_store: Stoplight.default_data_store,
|
10
|
-
notifiers: Stoplight.default_notifiers,
|
11
|
-
error_notifier: Stoplight.default_error_notifier,
|
12
|
-
cool_off_time: Stoplight::Default::COOL_OFF_TIME,
|
13
|
-
threshold: Stoplight::Default::THRESHOLD,
|
14
|
-
window_size: Stoplight::Default::WINDOW_SIZE
|
15
|
-
)
|
16
|
-
end
|
17
|
-
|
18
|
-
shared_examples 'configurable attribute' do |attribute|
|
19
|
-
subject(:with_attribute) do
|
20
|
-
configurable.__send__("with_#{attribute}", __send__(attribute))
|
21
|
-
end
|
22
|
-
|
23
|
-
it "configures #{attribute}" do
|
24
|
-
expect(with_attribute.configuration.__send__(attribute)).to eq(__send__(attribute))
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
describe '#with_data_store' do
|
29
|
-
let(:data_store) { instance_double(Stoplight::DataStore::Redis) }
|
30
|
-
|
31
|
-
include_examples 'configurable attribute', :data_store
|
32
|
-
end
|
33
|
-
|
34
|
-
describe '#cool_off_time' do
|
35
|
-
let(:cool_off_time) { 1_000 }
|
36
|
-
|
37
|
-
include_examples 'configurable attribute', :cool_off_time
|
38
|
-
end
|
39
|
-
|
40
|
-
describe '#with_threshold' do
|
41
|
-
let(:threshold) { 1_000 }
|
42
|
-
|
43
|
-
include_examples 'configurable attribute', :threshold
|
44
|
-
end
|
45
|
-
|
46
|
-
describe '#with_window_size' do
|
47
|
-
let(:window_size) { 1_000 }
|
48
|
-
|
49
|
-
include_examples 'configurable attribute', :window_size
|
50
|
-
end
|
51
|
-
|
52
|
-
describe '#with_notifiers' do
|
53
|
-
let(:notifiers) { 1_000 }
|
54
|
-
|
55
|
-
include_examples 'configurable attribute', :notifiers
|
56
|
-
end
|
57
|
-
|
58
|
-
describe '#with_error_notifier' do
|
59
|
-
let(:error_notifier) { ->(x) { x } }
|
60
|
-
|
61
|
-
subject(:with_attribute) do
|
62
|
-
configurable.with_error_notifier(&error_notifier)
|
63
|
-
end
|
64
|
-
|
65
|
-
it 'configures error notifier' do
|
66
|
-
expect(with_attribute.configuration.error_notifier).to eq(error_notifier)
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.shared_examples 'Stoplight::DataStore::Base#clear_failures' do
|
4
|
-
before do
|
5
|
-
data_store.record_failure(light, failure)
|
6
|
-
end
|
7
|
-
|
8
|
-
it 'returns the failures' do
|
9
|
-
expect(data_store.clear_failures(light)).to contain_exactly(failure)
|
10
|
-
end
|
11
|
-
|
12
|
-
it 'clears the failures' do
|
13
|
-
expect do
|
14
|
-
data_store.clear_failures(light)
|
15
|
-
end.to change { data_store.get_failures(light) }
|
16
|
-
.from([failure]).to(be_empty)
|
17
|
-
end
|
18
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.shared_examples 'Stoplight::DataStore::Base#clear_state' do
|
4
|
-
let(:state) { 'state' }
|
5
|
-
|
6
|
-
it 'returns the state' do
|
7
|
-
data_store.set_state(light, state)
|
8
|
-
|
9
|
-
expect(data_store.clear_state(light)).to eql(state)
|
10
|
-
end
|
11
|
-
|
12
|
-
it 'clears the state' do
|
13
|
-
data_store.set_state(light, state)
|
14
|
-
|
15
|
-
expect do
|
16
|
-
data_store.clear_state(light)
|
17
|
-
end.to change { data_store.get_state(light) }
|
18
|
-
.from(state).to(Stoplight::State::UNLOCKED)
|
19
|
-
end
|
20
|
-
end
|
@@ -1,44 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.shared_examples 'Stoplight::DataStore::Base#get_all' do
|
4
|
-
context 'when there are no errors' do
|
5
|
-
it 'returns the failures and the state' do
|
6
|
-
failures, state = data_store.get_all(light)
|
7
|
-
|
8
|
-
expect(failures).to eql([])
|
9
|
-
expect(state).to eql(Stoplight::State::UNLOCKED)
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
context 'when there are errors' do
|
14
|
-
before do
|
15
|
-
data_store.record_failure(light, failure)
|
16
|
-
end
|
17
|
-
|
18
|
-
it 'returns the failures and the state' do
|
19
|
-
failures, state = data_store.get_all(light)
|
20
|
-
|
21
|
-
expect(failures).to eq([failure])
|
22
|
-
expect(state).to eql(Stoplight::State::UNLOCKED)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
context 'when there is a failure outside of the window' do
|
27
|
-
let(:window_size) { 3600 }
|
28
|
-
let(:older_failure) { Stoplight::Failure.new('class', 'message 3', Time.new - window_size - 1) }
|
29
|
-
|
30
|
-
before do
|
31
|
-
light.with_window_size(window_size)
|
32
|
-
|
33
|
-
data_store.record_failure(light, older_failure)
|
34
|
-
data_store.record_failure(light, failure)
|
35
|
-
end
|
36
|
-
|
37
|
-
it 'returns the failures within window and the state' do
|
38
|
-
failures, state = data_store.get_all(light)
|
39
|
-
|
40
|
-
expect(failures).to contain_exactly(failure)
|
41
|
-
expect(state).to eql(Stoplight::State::UNLOCKED)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
@@ -1,30 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.shared_examples 'Stoplight::DataStore::Base#get_failures' do
|
4
|
-
it 'is initially empty' do
|
5
|
-
expect(data_store.get_failures(light)).to eql([])
|
6
|
-
end
|
7
|
-
|
8
|
-
it 'handles invalid JSON' do
|
9
|
-
expect { data_store.record_failure(light, failure) }
|
10
|
-
.to change { data_store.get_failures(light) }
|
11
|
-
.from(be_empty)
|
12
|
-
.to(contain_exactly(failure))
|
13
|
-
end
|
14
|
-
|
15
|
-
context 'when there is a failure outside of the window' do
|
16
|
-
let(:window_size) { 3600 }
|
17
|
-
let(:older_failure) { Stoplight::Failure.new('class', 'message 3', Time.new - window_size - 1) }
|
18
|
-
|
19
|
-
before do
|
20
|
-
light.with_window_size(window_size)
|
21
|
-
|
22
|
-
data_store.record_failure(light, failure)
|
23
|
-
data_store.record_failure(light, older_failure)
|
24
|
-
end
|
25
|
-
|
26
|
-
it 'returns failures withing given window' do
|
27
|
-
expect(data_store.get_failures(light)).to contain_exactly(failure)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
@@ -1,29 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.shared_examples 'Stoplight::DataStore::Base#names' do
|
4
|
-
it 'is initially empty' do
|
5
|
-
expect(data_store.names).to eql([])
|
6
|
-
end
|
7
|
-
|
8
|
-
it 'contains the name of a light with a failure' do
|
9
|
-
data_store.record_failure(light, failure)
|
10
|
-
expect(data_store.names).to eql([light.name])
|
11
|
-
end
|
12
|
-
|
13
|
-
it 'contains the name of a light with a set state' do
|
14
|
-
data_store.set_state(light, Stoplight::State::UNLOCKED)
|
15
|
-
expect(data_store.names).to eql([light.name])
|
16
|
-
end
|
17
|
-
|
18
|
-
it 'does not duplicate names' do
|
19
|
-
data_store.record_failure(light, failure)
|
20
|
-
data_store.set_state(light, Stoplight::State::UNLOCKED)
|
21
|
-
expect(data_store.names).to eql([light.name])
|
22
|
-
end
|
23
|
-
|
24
|
-
it 'supports names containing colons' do
|
25
|
-
light = Stoplight::Light.new('http://api.example.com/some/action')
|
26
|
-
data_store.record_failure(light, failure)
|
27
|
-
expect(data_store.names).to eql([light.name])
|
28
|
-
end
|
29
|
-
end
|