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.
Files changed (105) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +289 -350
  3. data/lib/stoplight/admin/actions/action.rb +24 -0
  4. data/lib/stoplight/admin/actions/lock.rb +23 -0
  5. data/lib/stoplight/admin/actions/lock_all_green.rb +18 -0
  6. data/lib/stoplight/admin/actions/lock_green.rb +23 -0
  7. data/lib/stoplight/admin/actions/lock_red.rb +23 -0
  8. data/lib/stoplight/admin/actions/stats.rb +27 -0
  9. data/lib/stoplight/admin/actions/unlock.rb +23 -0
  10. data/lib/stoplight/admin/dependencies.rb +50 -0
  11. data/lib/stoplight/admin/helpers.rb +27 -0
  12. data/lib/stoplight/admin/lights_repository/light.rb +155 -0
  13. data/lib/stoplight/admin/lights_repository.rb +74 -0
  14. data/lib/stoplight/admin/lights_stats.rb +77 -0
  15. data/lib/stoplight/admin/views/_card.erb +120 -0
  16. data/lib/stoplight/admin/views/index.erb +36 -0
  17. data/lib/stoplight/admin/views/layout.erb +66 -0
  18. data/lib/stoplight/admin.rb +68 -0
  19. data/lib/stoplight/color.rb +3 -3
  20. data/lib/stoplight/config/config_provider.rb +62 -0
  21. data/lib/stoplight/config/library_default_config.rb +29 -0
  22. data/lib/stoplight/config/user_default_config.rb +83 -0
  23. data/lib/stoplight/data_store/base.rb +59 -33
  24. data/lib/stoplight/data_store/fail_safe.rb +105 -0
  25. data/lib/stoplight/data_store/memory.rb +257 -50
  26. data/lib/stoplight/data_store/redis/get_metadata.lua +38 -0
  27. data/lib/stoplight/data_store/redis/lua.rb +23 -0
  28. data/lib/stoplight/data_store/redis/record_failure.lua +36 -0
  29. data/lib/stoplight/data_store/redis/record_success.lua +35 -0
  30. data/lib/stoplight/data_store/redis/transition_to_green.lua +10 -0
  31. data/lib/stoplight/data_store/redis/transition_to_red.lua +10 -0
  32. data/lib/stoplight/data_store/redis/transition_to_yellow.lua +9 -0
  33. data/lib/stoplight/data_store/redis.rb +345 -106
  34. data/lib/stoplight/default.rb +11 -9
  35. data/lib/stoplight/error.rb +1 -13
  36. data/lib/stoplight/failure.rb +14 -13
  37. data/lib/stoplight/light/config.rb +118 -0
  38. data/lib/stoplight/light/configuration_builder_interface.rb +128 -0
  39. data/lib/stoplight/light/green_run_strategy.rb +53 -0
  40. data/lib/stoplight/light/red_run_strategy.rb +26 -0
  41. data/lib/stoplight/light/run_strategy.rb +30 -0
  42. data/lib/stoplight/light/yellow_run_strategy.rb +78 -0
  43. data/lib/stoplight/light.rb +164 -84
  44. data/lib/stoplight/metadata.rb +71 -0
  45. data/lib/stoplight/notifier/base.rb +14 -7
  46. data/lib/stoplight/notifier/fail_safe.rb +67 -0
  47. data/lib/stoplight/notifier/generic.rb +54 -5
  48. data/lib/stoplight/rspec/generic_notifier.rb +11 -12
  49. data/lib/stoplight/rspec.rb +1 -1
  50. data/lib/stoplight/state.rb +3 -3
  51. data/lib/stoplight/traffic_control/base.rb +35 -0
  52. data/lib/stoplight/traffic_control/consecutive_failures.rb +43 -0
  53. data/lib/stoplight/traffic_recovery/base.rb +51 -0
  54. data/lib/stoplight/traffic_recovery/single_success.rb +35 -0
  55. data/lib/stoplight/version.rb +1 -1
  56. data/lib/stoplight.rb +111 -51
  57. metadata +49 -98
  58. data/lib/stoplight/builder.rb +0 -70
  59. data/lib/stoplight/circuit_breaker.rb +0 -102
  60. data/lib/stoplight/configurable.rb +0 -95
  61. data/lib/stoplight/configuration.rb +0 -126
  62. data/lib/stoplight/light/deprecated.rb +0 -44
  63. data/lib/stoplight/light/lockable.rb +0 -45
  64. data/lib/stoplight/light/runnable.rb +0 -127
  65. data/lib/stoplight/notifier.rb +0 -6
  66. data/spec/spec_helper.rb +0 -22
  67. data/spec/stoplight/builder_spec.rb +0 -165
  68. data/spec/stoplight/circuit_breaker_spec.rb +0 -43
  69. data/spec/stoplight/color_spec.rb +0 -39
  70. data/spec/stoplight/configurable_spec.rb +0 -25
  71. data/spec/stoplight/data_store/base_spec.rb +0 -71
  72. data/spec/stoplight/data_store/memory_spec.rb +0 -22
  73. data/spec/stoplight/data_store/redis_spec.rb +0 -45
  74. data/spec/stoplight/data_store_spec.rb +0 -9
  75. data/spec/stoplight/default_spec.rb +0 -80
  76. data/spec/stoplight/error_spec.rb +0 -39
  77. data/spec/stoplight/failure_spec.rb +0 -108
  78. data/spec/stoplight/light/lockable_spec.rb +0 -93
  79. data/spec/stoplight/light/runnable_spec.rb +0 -38
  80. data/spec/stoplight/light_spec.rb +0 -156
  81. data/spec/stoplight/notifier/base_spec.rb +0 -18
  82. data/spec/stoplight/notifier/generic_spec.rb +0 -50
  83. data/spec/stoplight/notifier/io_spec.rb +0 -41
  84. data/spec/stoplight/notifier/logger_spec.rb +0 -75
  85. data/spec/stoplight/notifier_spec.rb +0 -9
  86. data/spec/stoplight/state_spec.rb +0 -39
  87. data/spec/stoplight/version_spec.rb +0 -9
  88. data/spec/stoplight_spec.rb +0 -32
  89. data/spec/support/configurable.rb +0 -69
  90. data/spec/support/data_store/base/clear_failures.rb +0 -18
  91. data/spec/support/data_store/base/clear_state.rb +0 -20
  92. data/spec/support/data_store/base/get_all.rb +0 -44
  93. data/spec/support/data_store/base/get_failures.rb +0 -30
  94. data/spec/support/data_store/base/get_state.rb +0 -7
  95. data/spec/support/data_store/base/names.rb +0 -29
  96. data/spec/support/data_store/base/record_failures.rb +0 -70
  97. data/spec/support/data_store/base/set_state.rb +0 -15
  98. data/spec/support/data_store/base/with_notification_lock.rb +0 -27
  99. data/spec/support/data_store/base.rb +0 -21
  100. data/spec/support/database_cleaner.rb +0 -26
  101. data/spec/support/exception_helpers.rb +0 -9
  102. data/spec/support/light/runnable/color.rb +0 -79
  103. data/spec/support/light/runnable/run.rb +0 -247
  104. data/spec/support/light/runnable/state.rb +0 -31
  105. 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,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
-
5
- RSpec.describe Stoplight::Notifier do
6
- it 'is a module' do
7
- expect(described_class).to be_a(Module)
8
- end
9
- 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
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
-
5
- RSpec.describe Stoplight::VERSION do
6
- it 'is a gem version' do
7
- expect(described_class).to be_a(Gem::Version)
8
- end
9
- end
@@ -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,7 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.shared_examples 'Stoplight::DataStore::Base#get_state' do
4
- it 'is initially unlocked' do
5
- expect(data_store.get_state(light)).to eql(Stoplight::State::UNLOCKED)
6
- end
7
- 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