stoplight 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +15 -0
  3. data/LICENSE.md +1 -1
  4. data/README.md +66 -63
  5. data/lib/stoplight.rb +10 -15
  6. data/lib/stoplight/color.rb +9 -0
  7. data/lib/stoplight/data_store.rb +0 -146
  8. data/lib/stoplight/data_store/base.rb +7 -130
  9. data/lib/stoplight/data_store/memory.rb +25 -100
  10. data/lib/stoplight/data_store/redis.rb +61 -119
  11. data/lib/stoplight/default.rb +34 -0
  12. data/lib/stoplight/error.rb +0 -42
  13. data/lib/stoplight/failure.rb +21 -25
  14. data/lib/stoplight/light.rb +42 -127
  15. data/lib/stoplight/light/runnable.rb +97 -0
  16. data/lib/stoplight/notifier/base.rb +1 -4
  17. data/lib/stoplight/notifier/hip_chat.rb +17 -32
  18. data/lib/stoplight/notifier/io.rb +9 -9
  19. data/lib/stoplight/state.rb +9 -0
  20. data/spec/spec_helper.rb +2 -3
  21. data/spec/stoplight/color_spec.rb +39 -0
  22. data/spec/stoplight/data_store/base_spec.rb +56 -36
  23. data/spec/stoplight/data_store/memory_spec.rb +120 -2
  24. data/spec/stoplight/data_store/redis_spec.rb +123 -24
  25. data/spec/stoplight/data_store_spec.rb +2 -69
  26. data/spec/stoplight/default_spec.rb +86 -0
  27. data/spec/stoplight/error_spec.rb +29 -0
  28. data/spec/stoplight/failure_spec.rb +61 -51
  29. data/spec/stoplight/light/runnable_spec.rb +234 -0
  30. data/spec/stoplight/light_spec.rb +143 -191
  31. data/spec/stoplight/notifier/base_spec.rb +8 -11
  32. data/spec/stoplight/notifier/hip_chat_spec.rb +66 -55
  33. data/spec/stoplight/notifier/io_spec.rb +49 -21
  34. data/spec/stoplight/notifier_spec.rb +3 -0
  35. data/spec/stoplight/state_spec.rb +39 -0
  36. data/spec/stoplight_spec.rb +2 -65
  37. metadata +55 -19
  38. data/spec/support/data_store.rb +0 -36
  39. data/spec/support/fakeredis.rb +0 -3
  40. data/spec/support/hipchat.rb +0 -3
@@ -3,32 +3,60 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  describe Stoplight::Notifier::IO do
6
- subject(:notifier) { described_class.new(io, formatter) }
7
- let(:io) { StringIO.new }
8
- let(:formatter) { nil }
6
+ it 'is a class' do
7
+ expect(described_class).to be_a(Module)
8
+ end
9
+
10
+ it 'is a subclass of Base' do
11
+ expect(described_class).to be < Stoplight::Notifier::Base
12
+ end
13
+
14
+ describe '#formatter' do
15
+ it 'is initially the default' do
16
+ expect(described_class.new(nil).formatter)
17
+ .to eql(Stoplight::Default::FORMATTER)
18
+ end
19
+
20
+ it 'reads the formatter' do
21
+ formatter = proc {}
22
+ expect(described_class.new(nil, formatter).formatter)
23
+ .to eql(formatter)
24
+ end
25
+ end
26
+
27
+ describe '#io' do
28
+ it 'reads the IO' do
29
+ io = StringIO.new
30
+ expect(described_class.new(io).io).to eql(io)
31
+ end
32
+ end
9
33
 
10
34
  describe '#notify' do
11
- subject(:result) { notifier.notify(light, from_color, to_color) }
12
- let(:light) { Stoplight::Light.new(light_name, &light_code) }
13
- let(:light_name) { SecureRandom.hex }
14
- let(:light_code) { -> {} }
15
- let(:from_color) { Stoplight::DataStore::COLOR_GREEN }
16
- let(:to_color) { Stoplight::DataStore::COLOR_RED }
17
-
18
- it 'emits the message as a warning' do
19
- result
20
- expect(io.string)
21
- .to eql("Switching #{light.name} from #{from_color} to #{to_color}\n")
35
+ let(:light) { Stoplight::Light.new(name, &code) }
36
+ let(:name) { ('a'..'z').to_a.shuffle.join }
37
+ let(:code) { -> {} }
38
+ let(:from_color) { Stoplight::Color::GREEN }
39
+ let(:to_color) { Stoplight::Color::RED }
40
+ let(:notifier) { described_class.new(io) }
41
+ let(:io) { StringIO.new }
42
+
43
+ it 'returns the message' do
44
+ error = nil
45
+ expect(notifier.notify(light, from_color, to_color, error))
46
+ .to eql(notifier.formatter.call(light, from_color, to_color, error))
22
47
  end
23
48
 
24
- context 'with a formatter' do
25
- let(:formatter) { ->(l, f, t) { "#{l.name} #{f} #{t}" } }
49
+ it 'returns the message with an error' do
50
+ error = ZeroDivisionError.new('divided by 0')
51
+ expect(notifier.notify(light, from_color, to_color, error))
52
+ .to eql(notifier.formatter.call(light, from_color, to_color, error))
53
+ end
26
54
 
27
- it 'formats the message' do
28
- result
29
- expect(io.string)
30
- .to eql("#{light.name} #{from_color} #{to_color}\n")
31
- end
55
+ it 'writes the message' do
56
+ error = nil
57
+ notifier.notify(light, from_color, to_color, error)
58
+ message = notifier.formatter.call(light, from_color, to_color, error)
59
+ expect(io.string).to eql("#{message}\n")
32
60
  end
33
61
  end
34
62
  end
@@ -3,4 +3,7 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  describe Stoplight::Notifier do
6
+ it 'is a module' do
7
+ expect(described_class).to be_a(Module)
8
+ end
6
9
  end
@@ -0,0 +1,39 @@
1
+ # coding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ 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
@@ -3,70 +3,7 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  describe Stoplight do
6
- let(:name) { SecureRandom.hex }
7
-
8
- describe '::VERSION' do
9
- subject(:result) { described_class.const_get(:VERSION) }
10
-
11
- it 'is a Gem::Version' do
12
- expect(result).to be_a(Gem::Version)
13
- end
14
- end
15
-
16
- describe '.data_store' do
17
- subject(:result) { described_class.data_store }
18
-
19
- it 'uses the default data store' do
20
- expect(result).to be_a(Stoplight::DataStore::Memory)
21
- end
22
-
23
- it 'memoizes the result' do
24
- expect(result).to be described_class.data_store
25
- end
26
-
27
- context 'with a custom data store' do
28
- let(:data_store) { double }
29
-
30
- before do
31
- @data_store = described_class.data_store
32
- described_class.data_store = data_store
33
- end
34
-
35
- after { described_class.data_store = @data_store }
36
-
37
- it 'returns the data store' do
38
- expect(result).to eql(data_store)
39
- end
40
- end
41
- end
42
-
43
- describe '.notifiers' do
44
- subject(:result) { described_class.notifiers }
45
-
46
- it 'uses the default notifier' do
47
- expect(result).to be_an(Array)
48
- expect(result.size).to eql(1)
49
- expect(result.first).to be_a(Stoplight::Notifier::IO)
50
- end
51
-
52
- it 'memoizes the result' do
53
- expect(result).to be described_class.notifiers
54
- end
55
-
56
- context 'with custom notifiers' do
57
- let(:notifiers) { [notifier] }
58
- let(:notifier) { double }
59
-
60
- before do
61
- @notifiers = described_class.notifiers
62
- described_class.notifiers = notifiers
63
- end
64
-
65
- after { described_class.notifiers = @notifiers }
66
-
67
- it 'returns the notifiers' do
68
- expect(result).to eql(notifiers)
69
- end
70
- end
6
+ it 'is a module' do
7
+ expect(described_class).to be_a(Module)
71
8
  end
72
9
  end
metadata CHANGED
@@ -1,15 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stoplight
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cameron Desautels
8
8
  - Taylor Fausak
9
+ - Justin Steffy
9
10
  autorequire:
10
11
  bindir: bin
11
12
  cert_chain: []
12
- date: 2014-10-03 00:00:00.000000000 Z
13
+ date: 2014-11-19 00:00:00.000000000 Z
13
14
  dependencies:
14
15
  - !ruby/object:Gem::Dependency
15
16
  name: benchmark-ips
@@ -17,14 +18,14 @@ dependencies:
17
18
  requirements:
18
19
  - - ~>
19
20
  - !ruby/object:Gem::Version
20
- version: '2.0'
21
+ version: '2.1'
21
22
  type: :development
22
23
  prerelease: false
23
24
  version_requirements: !ruby/object:Gem::Requirement
24
25
  requirements:
25
26
  - - ~>
26
27
  - !ruby/object:Gem::Version
27
- version: '2.0'
28
+ version: '2.1'
28
29
  - !ruby/object:Gem::Dependency
29
30
  name: coveralls
30
31
  requirement: !ruby/object:Gem::Requirement
@@ -59,14 +60,14 @@ dependencies:
59
60
  requirements:
60
61
  - - ~>
61
62
  - !ruby/object:Gem::Version
62
- version: '1.3'
63
+ version: '1.4'
63
64
  type: :development
64
65
  prerelease: false
65
66
  version_requirements: !ruby/object:Gem::Requirement
66
67
  requirements:
67
68
  - - ~>
68
69
  - !ruby/object:Gem::Version
69
- version: '1.3'
70
+ version: '1.4'
70
71
  - !ruby/object:Gem::Dependency
71
72
  name: rake
72
73
  requirement: !ruby/object:Gem::Requirement
@@ -81,6 +82,20 @@ dependencies:
81
82
  - - ~>
82
83
  - !ruby/object:Gem::Version
83
84
  version: '10.3'
85
+ - !ruby/object:Gem::Dependency
86
+ name: redis
87
+ requirement: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ~>
90
+ - !ruby/object:Gem::Version
91
+ version: '3.1'
92
+ type: :development
93
+ prerelease: false
94
+ version_requirements: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ~>
97
+ - !ruby/object:Gem::Version
98
+ version: '3.1'
84
99
  - !ruby/object:Gem::Dependency
85
100
  name: rspec
86
101
  requirement: !ruby/object:Gem::Requirement
@@ -101,14 +116,28 @@ dependencies:
101
116
  requirements:
102
117
  - - ~>
103
118
  - !ruby/object:Gem::Version
104
- version: '0.26'
119
+ version: '0.27'
105
120
  type: :development
106
121
  prerelease: false
107
122
  version_requirements: !ruby/object:Gem::Requirement
108
123
  requirements:
109
124
  - - ~>
110
125
  - !ruby/object:Gem::Version
111
- version: '0.26'
126
+ version: '0.27'
127
+ - !ruby/object:Gem::Dependency
128
+ name: timecop
129
+ requirement: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - ~>
132
+ - !ruby/object:Gem::Version
133
+ version: '0.7'
134
+ type: :development
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - ~>
139
+ - !ruby/object:Gem::Version
140
+ version: '0.7'
112
141
  - !ruby/object:Gem::Dependency
113
142
  name: yard
114
143
  requirement: !ruby/object:Gem::Requirement
@@ -123,12 +152,11 @@ dependencies:
123
152
  - - ~>
124
153
  - !ruby/object:Gem::Version
125
154
  version: '0.8'
126
- description: |
127
- Traffic control for code. An implementation of the circuit breaker pattern
128
- in Ruby.
155
+ description: An implementation of the circuit breaker pattern.
129
156
  email:
130
157
  - camdez@gmail.com
131
158
  - taylor@fausak.me
159
+ - steffy@orgsync.com
132
160
  executables: []
133
161
  extensions: []
134
162
  extra_rdoc_files: []
@@ -138,33 +166,39 @@ files:
138
166
  - LICENSE.md
139
167
  - README.md
140
168
  - lib/stoplight.rb
169
+ - lib/stoplight/color.rb
141
170
  - lib/stoplight/data_store.rb
142
171
  - lib/stoplight/data_store/base.rb
143
172
  - lib/stoplight/data_store/memory.rb
144
173
  - lib/stoplight/data_store/redis.rb
174
+ - lib/stoplight/default.rb
145
175
  - lib/stoplight/error.rb
146
176
  - lib/stoplight/failure.rb
147
177
  - lib/stoplight/light.rb
178
+ - lib/stoplight/light/runnable.rb
148
179
  - lib/stoplight/notifier.rb
149
180
  - lib/stoplight/notifier/base.rb
150
181
  - lib/stoplight/notifier/hip_chat.rb
151
182
  - lib/stoplight/notifier/io.rb
183
+ - lib/stoplight/state.rb
152
184
  - spec/spec_helper.rb
185
+ - spec/stoplight/color_spec.rb
153
186
  - spec/stoplight/data_store/base_spec.rb
154
187
  - spec/stoplight/data_store/memory_spec.rb
155
188
  - spec/stoplight/data_store/redis_spec.rb
156
189
  - spec/stoplight/data_store_spec.rb
190
+ - spec/stoplight/default_spec.rb
191
+ - spec/stoplight/error_spec.rb
157
192
  - spec/stoplight/failure_spec.rb
193
+ - spec/stoplight/light/runnable_spec.rb
158
194
  - spec/stoplight/light_spec.rb
159
195
  - spec/stoplight/notifier/base_spec.rb
160
196
  - spec/stoplight/notifier/hip_chat_spec.rb
161
197
  - spec/stoplight/notifier/io_spec.rb
162
198
  - spec/stoplight/notifier_spec.rb
199
+ - spec/stoplight/state_spec.rb
163
200
  - spec/stoplight_spec.rb
164
- - spec/support/data_store.rb
165
- - spec/support/fakeredis.rb
166
- - spec/support/hipchat.rb
167
- homepage: http://orgsync.github.io/stoplight
201
+ homepage: https://github.com/orgsync/stoplight
168
202
  licenses:
169
203
  - MIT
170
204
  metadata: {}
@@ -184,24 +218,26 @@ required_rubygems_version: !ruby/object:Gem::Requirement
184
218
  version: '0'
185
219
  requirements: []
186
220
  rubyforge_project:
187
- rubygems_version: 2.4.1
221
+ rubygems_version: 2.4.3
188
222
  signing_key:
189
223
  specification_version: 4
190
224
  summary: Traffic control for code.
191
225
  test_files:
192
226
  - spec/spec_helper.rb
227
+ - spec/stoplight/color_spec.rb
193
228
  - spec/stoplight/data_store/base_spec.rb
194
229
  - spec/stoplight/data_store/memory_spec.rb
195
230
  - spec/stoplight/data_store/redis_spec.rb
196
231
  - spec/stoplight/data_store_spec.rb
232
+ - spec/stoplight/default_spec.rb
233
+ - spec/stoplight/error_spec.rb
197
234
  - spec/stoplight/failure_spec.rb
235
+ - spec/stoplight/light/runnable_spec.rb
198
236
  - spec/stoplight/light_spec.rb
199
237
  - spec/stoplight/notifier/base_spec.rb
200
238
  - spec/stoplight/notifier/hip_chat_spec.rb
201
239
  - spec/stoplight/notifier/io_spec.rb
202
240
  - spec/stoplight/notifier_spec.rb
241
+ - spec/stoplight/state_spec.rb
203
242
  - spec/stoplight_spec.rb
204
- - spec/support/data_store.rb
205
- - spec/support/fakeredis.rb
206
- - spec/support/hipchat.rb
207
243
  has_rdoc:
@@ -1,36 +0,0 @@
1
- # coding: utf-8
2
- # rubocop:disable Metrics/LineLength
3
-
4
- shared_examples_for 'a data store' do
5
- let(:name) { SecureRandom.hex }
6
- let(:failure) { Stoplight::Failure.new(error, time) }
7
- let(:error) { error_class.new }
8
- let(:error_class) { Class.new(StandardError) }
9
- let(:time) { Time.now }
10
- let(:state) { Stoplight::DataStore::STATES.to_a.sample }
11
- let(:threshold) { 1 + rand(100) }
12
- let(:timeout) { rand(100) }
13
-
14
- it { expect(data_store.names).to eql([]) }
15
- it { expect(data_store.get_color(name)).to eql(Stoplight::DataStore::COLOR_GREEN) }
16
- it { expect(data_store.green?(name)).to eql(true) }
17
- it { expect(data_store.yellow?(name)).to eql(false) }
18
- it { expect(data_store.red?(name)).to eql(false) }
19
- it { expect(data_store.get_attempts(name)).to eql(Stoplight::DataStore::DEFAULT_ATTEMPTS) }
20
- it { expect(data_store.record_attempt(name)).to eql(1) }
21
- it { expect(data_store.get_failures(name)).to eql(Stoplight::DataStore::DEFAULT_FAILURES) }
22
- it { expect(data_store.record_failure(name, failure)).to eql(failure) }
23
- it { expect(data_store.get_state(name)).to eql(Stoplight::DataStore::DEFAULT_STATE) }
24
- it { expect(data_store.set_state(name, state)).to eql(state) }
25
- it { expect(data_store.get_threshold(name)).to eql(Stoplight::DataStore::DEFAULT_THRESHOLD) }
26
- it { expect(data_store.set_threshold(name, threshold)).to eql(threshold) }
27
- it { expect(data_store.get_timeout(name)).to eql(Stoplight::DataStore::DEFAULT_TIMEOUT) }
28
- it { expect(data_store.set_timeout(name, timeout)).to eql(timeout) }
29
-
30
- it 'clears stale lights' do
31
- data_store.sync(name)
32
- expect(data_store.names).to include(name)
33
- data_store.clear_stale
34
- expect(data_store.names).to_not include(name)
35
- end
36
- end
@@ -1,3 +0,0 @@
1
- # coding: utf-8
2
-
3
- require 'fakeredis/rspec'
@@ -1,3 +0,0 @@
1
- # coding: utf-8
2
-
3
- require 'hipchat'