stoplight 0.5.1 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9619bee3f557017bc7b877349a5a2b5985e535ce
4
- data.tar.gz: 5dec1f7bce5d8373cea3747e8dc587e0795e19c2
3
+ metadata.gz: bcc53c7687a3a7fc307685f81463b7a97aec96bd
4
+ data.tar.gz: 7fe4bfe9357b1a52ffad84dbba77decbb8875979
5
5
  SHA512:
6
- metadata.gz: 9f12b3bbf04f13f74c91ef78c3c85909a720e15003808609bb9d06e5886643a52d17a83e37263e1dc10666dd286f8e3fdb2784652b553b35eafc47f920368d76
7
- data.tar.gz: 4437c4f2618ac10732bdccd600699590780d1d162d8f6523206115a283d0d616e389a58fbe7ea56c07010f087768ed9918fbd2f092177e9944ea33fc6b142bc0
6
+ metadata.gz: d2461d125e6b721bb12d38eddfa0047e823899febb818f7276006cea9a8da70cef5215efe77b6017b0fe3a3b92c389e0927306b385cdf347a3903d048fed989b
7
+ data.tar.gz: bd7939dd6723a2a405865aa756b9cc4d903b00931eff7796d3276ea98aa3d4b139b23809cd726ee3a17b446ca59a976a0095645283386d10ac2e65f1390c5290
data/CHANGELOG.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  This project uses [Semantic Versioning][1].
4
4
 
5
+ ## v0.5.2 (2014-11-19)
6
+
7
+ - Created a convenience function for creating stoplights.
8
+ - Created a `VERSION` constant.
9
+ - Added YARD type documentation for public methods.
10
+
5
11
  ## v0.5.1 (2014-11-19)
6
12
 
7
13
  - Fixed a logic bug that incorrectly determined red lights to be yellow.
data/LICENSE.md CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2014 Cameron Desautels, Taylor Fausak & Justin Steffy
1
+ Copyright (c) 2015 Cameron Desautels, Taylor Fausak & Justin Steffy
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy of
4
4
  this software and associated documentation files (the "Software"), to deal in
data/README.md CHANGED
@@ -1,17 +1,39 @@
1
- # [Stoplight][1]
2
-
3
- [![Gem version][2]][3]
4
- [![Build status][4]][5]
5
- [![Coverage status][6]][7]
6
- [![Quality status][8]][9]
7
- [![Dependency status][10]][11]
8
-
9
- <img align="right" alt="Stoplight icon" src="https://i.imgur.com/tiuOfY9.png">
10
-
11
- Traffic control for code. An implementation of the circuit breaker pattern in
12
- Ruby.
13
-
14
- Check out [stoplight-admin][12] for controlling your stoplights.
1
+ <p align="center">
2
+ <img alt="Stoplight" src="stoplight.png">
3
+ </p>
4
+
5
+ <h1 align="center">
6
+ <a href="https://github.com/orgsync/stoplight">
7
+ Stoplight
8
+ </a>
9
+ </h1>
10
+
11
+ <p align="center">
12
+ Stoplight is traffic control for code. It's an implementation of
13
+ the circuit breaker pattern in Ruby.
14
+ </p>
15
+
16
+ <p align="center">
17
+ <a href="https://rubygems.org/gems/stoplight">
18
+ <img alt="" src="https://img.shields.io/gem/v/stoplight.svg">
19
+ </a>
20
+ <a href="https://travis-ci.org/orgsync/stoplight">
21
+ <img alt="" src="https://img.shields.io/travis/orgsync/stoplight/master.svg">
22
+ </a>
23
+ <a href="https://coveralls.io/r/orgsync/stoplight">
24
+ <img alt="" src="https://img.shields.io/coveralls/orgsync/stoplight/master.svg">
25
+ </a>
26
+ <a href="https://codeclimate.com/github/orgsync/stoplight">
27
+ <img alt="" src="https://img.shields.io/codeclimate/github/orgsync/stoplight.svg">
28
+ </a>
29
+ <a href="https://gemnasium.com/orgsync/stoplight">
30
+ <img alt="" src="https://img.shields.io/gemnasium/orgsync/stoplight.svg">
31
+ </a>
32
+ </p>
33
+
34
+ <hr>
35
+
36
+ Check out [stoplight-admin][] for controlling your stoplights.
15
37
 
16
38
  - [Installation](#installation)
17
39
  - [Setup](#setup)
@@ -33,13 +55,13 @@ Check out [stoplight-admin][12] for controlling your stoplights.
33
55
  Add it to your Gemfile:
34
56
 
35
57
  ``` rb
36
- gem 'stoplight', '~> 0.5.1'
58
+ gem 'stoplight', '~> 0.5.2'
37
59
  ```
38
60
 
39
61
  Or install it manually:
40
62
 
41
63
  ``` sh
42
- $ gem install stoplight
64
+ $ gem install stoplight --version '~> 0.5.2'
43
65
  ```
44
66
 
45
67
  ## Setup
@@ -48,58 +70,60 @@ $ gem install stoplight
48
70
 
49
71
  Stoplight uses an in-memory data store out of the box.
50
72
 
51
- ``` irb
52
- >> require 'stoplight'
53
- => true
54
- >> Stoplight::Light.default_data_store
55
- => #<Stoplight::DataStore::Memory:...>
73
+ ``` rb
74
+ require 'stoplight'
75
+ # => true
76
+ Stoplight::Light.default_data_store
77
+ # => #<Stoplight::DataStore::Memory:...>
56
78
  ```
57
79
 
58
- If you want to use a persistent data store, you'll have to set it up. Currently
59
- the only supported persistent data store is Redis. Make sure you have [the Redis
60
- gem][13] installed before configuring Stoplight.
61
-
62
- ``` irb
63
- >> require 'redis'
64
- => true
65
- >> redis = Redis.new
66
- => #<Redis client ...>
67
- >> data_store = Stoplight::DataStore::Redis.new(redis)
68
- => #<Stoplight::DataStore::Redis:...>
69
- >> Stoplight::Light.default_data_store = data_store
70
- => #<Stoplight::DataStore::Redis:...>
80
+ If you want to use a persistent data store, you'll have to set it
81
+ up. Currently the only supported persistent data store is Redis.
82
+ Make sure you have [the Redis gem][] installed before configuring
83
+ Stoplight.
84
+
85
+ ``` rb
86
+ require 'redis'
87
+ # => true
88
+ redis = Redis.new
89
+ # => #<Redis client ...>
90
+ data_store = Stoplight::DataStore::Redis.new(redis)
91
+ # => #<Stoplight::DataStore::Redis:...>
92
+ Stoplight::Light.default_data_store = data_store
93
+ # => #<Stoplight::DataStore::Redis:...>
71
94
  ```
72
95
 
73
96
  ### Notifiers
74
97
 
75
98
  Stoplight sends notifications to standard error by default.
76
99
 
77
- ``` irb
78
- >> Stoplight::Light.default_notifiers
79
- => [#<Stoplight::Notifier::IO:...>]
100
+ ``` rb
101
+ Stoplight::Light.default_notifiers
102
+ # => [#<Stoplight::Notifier::IO:...>]
80
103
  ```
81
104
 
82
- If you want to send notifications elsewhere, you'll have to set them up.
83
- Currently the only other supported notifier is HipChat. Make sure you have [the
84
- HipChat gem][14] installed before configuring Stoplight.
85
-
86
- ``` irb
87
- >> require 'hipchat'
88
- => true
89
- >> hip_chat = HipChat::Client.new('token')
90
- => #<HipChat::Client:...>
91
- >> notifier = Stoplight::Notifier::HipChat.new(hip_chat, 'room')
92
- => #<Stoplight::Notifier::HipChat:...>
93
- >> Stoplight::Light.default_notifiers += [notifier]
94
- => [#<Stoplight::Notifier::IO:...>, #<Stoplight::Notifier::HipChat:...>]
105
+ If you want to send notifications elsewhere, you'll have to set
106
+ them up. Currently the only other supported notifier is HipChat.
107
+ Make sure you have [the HipChat gem][] installed before configuring
108
+ Stoplight.
109
+
110
+ ``` rb
111
+ require 'hipchat'
112
+ # => true
113
+ hip_chat = HipChat::Client.new('token')
114
+ # => #<HipChat::Client:...>
115
+ notifier = Stoplight::Notifier::HipChat.new(hip_chat, 'room')
116
+ # => #<Stoplight::Notifier::HipChat:...>
117
+ Stoplight::Light.default_notifiers += [notifier]
118
+ # => [#<Stoplight::Notifier::IO:...>, #<Stoplight::Notifier::HipChat:...>]
95
119
  ```
96
120
 
97
121
  ### Rails
98
122
 
99
- Stoplight is designed to work seamlessly with Rails. If you want to use the
100
- in-memory data store, you don't need to do anything special. If you want to use
101
- a persistent data store, you'll need to configure it. Create an initializer for
102
- Stoplight:
123
+ Stoplight is designed to work seamlessly with Rails. If you want
124
+ to use the in-memory data store, you don't need to do anything
125
+ special. If you want to use a persistent data store, you'll need
126
+ to configure it. Create an initializer for Stoplight:
103
127
 
104
128
  ``` rb
105
129
  # config/initializers/stoplight.rb
@@ -112,150 +136,152 @@ Stoplight::Light.default_notifiers += [Stoplight::Notifier::HipChat.new(...)]
112
136
 
113
137
  To get started, create a stoplight:
114
138
 
115
- ``` irb
116
- >> light = Stoplight::Light.new('example-1') { 22.0 / 7 }
117
- => #<Stoplight::Light:...>
139
+ ``` rb
140
+ light = Stoplight('example-1') { 22.0 / 7 }
141
+ # => #<Stoplight::Light:...>
118
142
  ```
119
143
 
120
- Then you can run it and it will return the result of calling the block. This is
121
- the green state.
144
+ Then you can run it and it will return the result of calling the
145
+ block. This is the green state.
122
146
 
123
- ``` irb
124
- >> light.run
125
- => 3.142857142857143
126
- >> light.color
127
- => "green"
147
+ ``` rb
148
+ light.run
149
+ # => 3.142857142857143
150
+ light.color
151
+ # => "green"
128
152
  ```
129
153
 
130
- If everything goes well, you shouldn't even be able to tell that you're using a
131
- stoplight. That's not very interesting though. Let's create a failing stoplight:
154
+ If everything goes well, you shouldn't even be able to tell that
155
+ you're using a stoplight. That's not very interesting though. Let's
156
+ create a failing stoplight:
132
157
 
133
- ``` irb
134
- >> light = Stoplight::Light.new('example-2') { 1 / 0 }
135
- => #<Stoplight::Light:...>
158
+ ``` rb
159
+ light = Stoplight('example-2') { 1 / 0 }
160
+ # => #<Stoplight::Light:...>
136
161
  ```
137
162
 
138
- Now when you run it, the error will be recorded and passed through. After
139
- running it a few times, the stoplight will stop trying and fail fast. This is
140
- the red state.
141
-
142
- ``` irb
143
- >> light.run
144
- ZeroDivisionError: divided by 0
145
- >> light.run
146
- ZeroDivisionError: divided by 0
147
- >> light.run
148
- Switching example-2 from green to red because ZeroDivisionError divided by 0
149
- ZeroDivisionError: divided by 0
150
- >> light.run
151
- Stoplight::Error::RedLight: example-2
152
- >> light.color
153
- => "red"
163
+ Now when you run it, the error will be recorded and passed through.
164
+ After running it a few times, the stoplight will stop trying and
165
+ fail fast. This is the red state.
166
+
167
+ ``` rb
168
+ light.run
169
+ # ZeroDivisionError: divided by 0
170
+ light.run
171
+ # ZeroDivisionError: divided by 0
172
+ light.run
173
+ # Switching example-2 from green to red because ZeroDivisionError divided by 0
174
+ # ZeroDivisionError: divided by 0
175
+ light.run
176
+ # Stoplight::Error::RedLight: example-2
177
+ light.color
178
+ # => "red"
154
179
  ```
155
180
 
156
- When the stoplight changes from green to red, it will notify every configured
157
- notifier.
181
+ When the stoplight changes from green to red, it will notify every
182
+ configured notifier.
158
183
 
159
184
  ### Custom errors
160
185
 
161
- Some errors shouldn't cause your stoplight to move into the red state. Usually
162
- these are handled elsewhere in your stack and don't represent real failures. A
163
- good example is `ActiveRecord::RecordNotFound`.
164
-
165
- ``` irb
166
- >> light = Stoplight::Light.new('example-3') { User.find(123) }.
167
- .. with_allowed_errors([ActiveRecord::RecordNotFound])
168
- => #<Stoplight::Light:...>
169
- >> light.run
170
- ActiveRecord::RecordNotFound: Couldn't find User with ID=123
171
- >> light.run
172
- ActiveRecord::RecordNotFound: Couldn't find User with ID=123
173
- >> light.run
174
- ActiveRecord::RecordNotFound: Couldn't find User with ID=123
175
- >> light.color
176
- => "green"
186
+ Some errors shouldn't cause your stoplight to move into the red
187
+ state. Usually these are handled elsewhere in your stack and don't
188
+ represent real failures. A good example is `ActiveRecord::RecordNotFound`.
189
+
190
+ ``` rb
191
+ light = Stoplight('example-3') { User.find(123) }
192
+ .with_allowed_errors([ActiveRecord::RecordNotFound])
193
+ # => #<Stoplight::Light:...>
194
+ light.run
195
+ # ActiveRecord::RecordNotFound: Couldn't find User with ID=123
196
+ light.run
197
+ # ActiveRecord::RecordNotFound: Couldn't find User with ID=123
198
+ light.run
199
+ # ActiveRecord::RecordNotFound: Couldn't find User with ID=123
200
+ light.color
201
+ # => "green"
177
202
  ```
178
203
 
179
204
  ### Custom fallback
180
205
 
181
- By default, stoplights will re-raise errors when they're green. When they're
182
- red, they'll raise a `Stoplight::Error::RedLight` error. You can provide a
183
- fallback that will be called in both of these cases. It will be passed the error
184
- if the light was green.
185
-
186
- ``` irb
187
- >> light = Stoplight::Light.new('example-4') { 1 / 0 }.
188
- .. with_fallback { |e| p e; 'default' }
189
- => #<Stoplight::Light:..>
190
- >> light.run
191
- #<ZeroDivisionError: divided by 0>
192
- => "default"
193
- >> light.run
194
- #<ZeroDivisionError: divided by 0>
195
- => "default"
196
- >> light.run
197
- Switching example-4 from green to red because ZeroDivisionError divided by 0
198
- #<ZeroDivisionError: divided by 0>
199
- => "default"
200
- >> light.run
201
- nil
202
- => "default"
206
+ By default, stoplights will re-raise errors when they're green.
207
+ When they're red, they'll raise a `Stoplight::Error::RedLight`
208
+ error. You can provide a fallback that will be called in both of
209
+ these cases. It will be passed the error if the light was green.
210
+
211
+ ``` rb
212
+ light = Stoplight('example-4') { 1 / 0 }
213
+ .with_fallback { |e| p e; 'default' }
214
+ # => #<Stoplight::Light:..>
215
+ light.run
216
+ # #<ZeroDivisionError: divided by 0>
217
+ # => "default"
218
+ light.run
219
+ # #<ZeroDivisionError: divided by 0>
220
+ # => "default"
221
+ light.run
222
+ # Switching example-4 from green to red because ZeroDivisionError divided by 0
223
+ # #<ZeroDivisionError: divided by 0>
224
+ # => "default"
225
+ light.run
226
+ # nil
227
+ # => "default"
203
228
  ```
204
229
 
205
230
  ### Custom threshold
206
231
 
207
- Some bits of code might be allowed to fail more or less frequently than others.
208
- You can configure this by setting a custom threshold in seconds.
209
-
210
- ``` irb
211
- >> light = Stoplight::Light.new('example-5') { fail }.
212
- .. with_threshold(1)
213
- => #<Stoplight::Light:...>
214
- >> light.run
215
- Switching example-5 from green to red because RuntimeError
216
- RuntimeError:
217
- >> light.run
218
- Stoplight::Error::RedLight: example-5
232
+ Some bits of code might be allowed to fail more or less frequently
233
+ than others. You can configure this by setting a custom threshold
234
+ in seconds.
235
+
236
+ ``` rb
237
+ light = Stoplight('example-5') { fail }
238
+ .with_threshold(1)
239
+ # => #<Stoplight::Light:...>
240
+ light.run
241
+ # Switching example-5 from green to red because RuntimeError
242
+ # RuntimeError:
243
+ light.run
244
+ # Stoplight::Error::RedLight: example-5
219
245
  ```
220
246
 
221
247
  ### Custom timeout
222
248
 
223
- Stoplights will automatically attempt to recover after a certain amount of time.
224
- A light in the red state for longer than the timeout will transition to the
225
- yellow state. This timeout is customizable.
226
-
227
- ``` irb
228
- >> light = Stoplight::Light.new('example-6') { fail }.
229
- .. with_timeout(1)
230
- => #<Stoplight::Light:...>
231
- >> light.run
232
- RuntimeError:
233
- >> light.run
234
- RuntimeError:
235
- >> light.run
236
- Switching example-6 from green to red because RuntimeError
237
- RuntimeError:
238
- >> sleep(1)
239
- => 1
240
- >> light.color
241
- => "yellow"
242
- >> light.run
243
- RuntimeError:
249
+ Stoplights will automatically attempt to recover after a certain
250
+ amount of time. A light in the red state for longer than the timeout
251
+ will transition to the yellow state. This timeout is customizable.
252
+
253
+ ``` rb
254
+ light = Stoplight('example-6') { fail }
255
+ .with_timeout(1)
256
+ # => #<Stoplight::Light:...>
257
+ light.run
258
+ # RuntimeError:
259
+ light.run
260
+ # RuntimeError:
261
+ light.run
262
+ # Switching example-6 from green to red because RuntimeError
263
+ # RuntimeError:
264
+ sleep(1)
265
+ # => 1
266
+ light.color
267
+ # => "yellow"
268
+ light.run
269
+ # RuntimeError:
244
270
  ```
245
271
 
246
272
  Set the timeout to `-1` to disable automatic recovery.
247
273
 
248
274
  ### Rails
249
275
 
250
- Stoplight was designed to wrap Rails actions with minimal effort. Here's an
251
- example configuration:
276
+ Stoplight was designed to wrap Rails actions with minimal effort.
277
+ Here's an example configuration:
252
278
 
253
279
  ``` rb
254
280
  class ApplicationController < ActionController::Base
255
281
  around_action :stoplight
256
282
  private
257
283
  def stoplight(&block)
258
- Stoplight::Light.new("#{params[:controller]}##{params[:action]}", &block)
284
+ Stoplight("#{params[:controller]}##{params[:action]}", &block)
259
285
  .with_allowed_errors([ActiveRecord::RecordNotFound])
260
286
  .with_fallback do |error|
261
287
  Rails.logger.error(error)
@@ -270,55 +296,39 @@ end
270
296
 
271
297
  ### Locking
272
298
 
273
- Although stoplights can operate on their own, occasionally you may want to
274
- override the default behavior. You can lock a light in either the green or red
275
- state using `set_state`.
276
-
277
- ``` irb
278
- >> light = Stoplight::Light.new('example-7') { true }
279
- => #<Stoplight::Light:..>
280
- >> light.run
281
- => true
282
- >> light.data_store.set_state(light, Stoplight::State::LOCKED_RED)
283
- => "locked_red"
284
- >> light.run
285
- Stoplight::Error::RedLight: example-7
299
+ Although stoplights can operate on their own, occasionally you may
300
+ want to override the default behavior. You can lock a light in
301
+ either the green or red state using `set_state`.
302
+
303
+ ``` rb
304
+ light = Stoplight('example-7') { true }
305
+ # => #<Stoplight::Light:..>
306
+ light.run
307
+ # => true
308
+ light.data_store.set_state(light, Stoplight::State::LOCKED_RED)
309
+ # => "locked_red"
310
+ light.run
311
+ # Stoplight::Error::RedLight: example-7
286
312
  ```
287
313
 
288
- **Code in locked red lights may still run under certain conditions!** If you
289
- have configured a custom data store and that data store fails, Stoplight will
290
- switch over to using a blank in-memory data store. That means you will lose the
291
- locked state of any stoplights.
314
+ **Code in locked red lights may still run under certain conditions!**
315
+ If you have configured a custom data store and that data store
316
+ fails, Stoplight will switch over to using a blank in-memory data
317
+ store. That means you will lose the locked state of any stoplights.
292
318
 
293
319
  ## Credits
294
320
 
295
- Stoplight is brought to you by [@camdez][15] and [@tfausak][16] from
296
- [@OrgSync][17]. We were inspired by Martin Fowler's [CircuitBreaker][18]
321
+ Stoplight is brought to you by [@camdez][] and [@tfausak][] from
322
+ [@OrgSync][]. We were inspired by Martin Fowler's [CircuitBreaker][]
297
323
  article.
298
324
 
299
- If this gem isn't cutting it for you, there are a few alternatives, including:
300
- [circuit_b][19], [circuit_breaker][20], [simple_circuit_breaker][21], and
301
- [ya_circuit_breaker][22].
302
-
303
- [1]: https://github.com/orgsync/stoplight
304
- [2]: https://badge.fury.io/rb/stoplight.svg
305
- [3]: https://rubygems.org/gems/stoplight
306
- [4]: https://travis-ci.org/orgsync/stoplight.svg
307
- [5]: https://travis-ci.org/orgsync/stoplight
308
- [6]: https://img.shields.io/coveralls/orgsync/stoplight.svg
309
- [7]: https://coveralls.io/r/orgsync/stoplight
310
- [8]: https://codeclimate.com/github/orgsync/stoplight/badges/gpa.svg
311
- [9]: https://codeclimate.com/github/orgsync/stoplight
312
- [10]: https://gemnasium.com/orgsync/stoplight.svg
313
- [11]: https://gemnasium.com/orgsync/stoplight
314
- [12]: https://github.com/orgsync/stoplight-admin
315
- [13]: https://rubygems.org/gems/redis
316
- [14]: https://rubygems.org/gems/hipchat
317
- [15]: https://github.com/camdez
318
- [16]: https://github.com/tfausak
319
- [17]: https://github.com/OrgSync
320
- [18]: http://martinfowler.com/bliki/CircuitBreaker.html
321
- [19]: https://github.com/alg/circuit_b
322
- [20]: https://github.com/wsargent/circuit_breaker
323
- [21]: https://github.com/soundcloud/simple_circuit_breaker
324
- [22]: https://github.com/wooga/circuit_breaker
325
+ Emoji provided free by [Emoji One][].
326
+
327
+ [stoplight-admin]: https://github.com/orgsync/stoplight-admin
328
+ [the redis gem]: https://rubygems.org/gems/redis
329
+ [the hipchat gem]: https://rubygems.org/gems/hipchat
330
+ [@camdez]: https://github.com/camdez
331
+ [@tfausak]: https://github.com/tfausak
332
+ [@orgsync]: https://github.com/OrgSync
333
+ [circuitbreaker]: http://martinfowler.com/bliki/CircuitBreaker.html
334
+ [emoji one]: http://www.emojione.com
data/lib/stoplight.rb CHANGED
@@ -1,5 +1,10 @@
1
1
  # coding: utf-8
2
2
 
3
+ module Stoplight
4
+ end
5
+
6
+ require 'stoplight/version'
7
+
3
8
  require 'stoplight/color'
4
9
  require 'stoplight/error'
5
10
  require 'stoplight/failure'
@@ -20,5 +25,7 @@ require 'stoplight/default'
20
25
  require 'stoplight/light/runnable'
21
26
  require 'stoplight/light'
22
27
 
23
- module Stoplight
28
+ # @see Stoplight::Light#initialize
29
+ def Stoplight(name, &code) # rubocop:disable Style/MethodName
30
+ Stoplight::Light.new(name, &code)
24
31
  end
@@ -2,35 +2,53 @@
2
2
 
3
3
  module Stoplight
4
4
  module DataStore
5
+ # @abstract
5
6
  class Base
7
+ # @return [Array<String>]
6
8
  def names
7
9
  fail NotImplementedError
8
10
  end
9
11
 
12
+ # @param _light [Light]
13
+ # @return [Array(Array<Failure>, String)]
10
14
  def get_all(_light)
11
15
  fail NotImplementedError
12
16
  end
13
17
 
18
+ # @param _light [Light]
19
+ # @return [Array<Failure>]
14
20
  def get_failures(_light)
15
21
  fail NotImplementedError
16
22
  end
17
23
 
24
+ # @param _light [Light]
25
+ # @param _failure [Failure]
26
+ # @return [Fixnum]
18
27
  def record_failure(_light, _failure)
19
28
  fail NotImplementedError
20
29
  end
21
30
 
31
+ # @param _light [Light]
32
+ # @return [Array<Failure>]
22
33
  def clear_failures(_light)
23
34
  fail NotImplementedError
24
35
  end
25
36
 
37
+ # @param _light [Light]
38
+ # @return [String]
26
39
  def get_state(_light)
27
40
  fail NotImplementedError
28
41
  end
29
42
 
43
+ # @param _light [Light]
44
+ # @param _state [String]
45
+ # @return [String]
30
46
  def set_state(_light, _state)
31
47
  fail NotImplementedError
32
48
  end
33
49
 
50
+ # @param _light [Light]
51
+ # @return [String]
34
52
  def clear_state(_light)
35
53
  fail NotImplementedError
36
54
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  module Stoplight
4
4
  module DataStore
5
+ # @see Base
5
6
  class Memory < Base
6
7
  def initialize
7
8
  @data = {}
@@ -2,10 +2,12 @@
2
2
 
3
3
  module Stoplight
4
4
  module DataStore
5
+ # @see Base
5
6
  class Redis < Base
6
7
  KEY_PREFIX = 'stoplight'.freeze
7
8
  KEY_SEPARATOR = ':'.freeze
8
9
 
10
+ # @param redis [::Redis]
9
11
  def initialize(redis)
10
12
  @redis = redis
11
13
  end
@@ -5,14 +5,23 @@ require 'time'
5
5
 
6
6
  module Stoplight
7
7
  class Failure
8
+ # @return [String]
8
9
  attr_reader :error_class
10
+ # @return [String]
9
11
  attr_reader :error_message
12
+ # @return [Time]
10
13
  attr_reader :time
11
14
 
15
+ # @param error [Exception]
16
+ # @return (see #initialize)
12
17
  def self.from_error(error)
13
18
  new(error.class.name, error.message, Time.new)
14
19
  end
15
20
 
21
+ # @param json [String]
22
+ # @return (see #initialize)
23
+ # @raise [JSON::ParserError]
24
+ # @raise [ArgumentError]
16
25
  def self.from_json(json)
17
26
  object = JSON.parse(json)
18
27
 
@@ -23,18 +32,24 @@ module Stoplight
23
32
  new(error_class, error_message, time)
24
33
  end
25
34
 
35
+ # @param error_class [String]
36
+ # @param error_message [String]
37
+ # @param time [Time]
26
38
  def initialize(error_class, error_message, time)
27
39
  @error_class = error_class
28
40
  @error_message = error_message
29
41
  @time = time
30
42
  end
31
43
 
44
+ # @param other [Failure]
45
+ # @return [Boolean]
32
46
  def ==(other)
33
47
  error_class == other.error_class &&
34
48
  error_message == other.error_message &&
35
49
  time == other.time
36
50
  end
37
51
 
52
+ # @return [String]
38
53
  def to_json
39
54
  JSON.generate(
40
55
  error: {
@@ -4,19 +4,31 @@ module Stoplight
4
4
  class Light
5
5
  include Runnable
6
6
 
7
+ # @return [Array<Exception>]
7
8
  attr_reader :allowed_errors
9
+ # @return [Proc]
8
10
  attr_reader :code
11
+ # @return [DataStore::Base]
9
12
  attr_reader :data_store
13
+ # @return [Proc]
10
14
  attr_reader :error_notifier
15
+ # @return [Proc, nil]
11
16
  attr_reader :fallback
17
+ # @return [String]
12
18
  attr_reader :name
19
+ # @return [Array<Notifier::Base>]
13
20
  attr_reader :notifiers
21
+ # @return [Fixnum]
14
22
  attr_reader :threshold
23
+ # @return [Float]
15
24
  attr_reader :timeout
16
25
 
17
26
  class << self
27
+ # @return [DataStore::Base]
18
28
  attr_accessor :default_data_store
29
+ # @return [Proc]
19
30
  attr_accessor :default_error_notifier
31
+ # @return [Array<Notifier::Base>]
20
32
  attr_accessor :default_notifiers
21
33
  end
22
34
 
@@ -24,6 +36,8 @@ module Stoplight
24
36
  @default_error_notifier = Default::ERROR_NOTIFIER
25
37
  @default_notifiers = Default::NOTIFIERS
26
38
 
39
+ # @param name [String]
40
+ # @yield []
27
41
  def initialize(name, &code)
28
42
  @name = name
29
43
  @code = code
@@ -37,36 +51,50 @@ module Stoplight
37
51
  @timeout = Default::TIMEOUT
38
52
  end
39
53
 
54
+ # @param allowed_errors [Array<Exception>]
55
+ # @return [self]
40
56
  def with_allowed_errors(allowed_errors)
41
57
  @allowed_errors = Default::ALLOWED_ERRORS + allowed_errors
42
58
  self
43
59
  end
44
60
 
61
+ # @param data_store [DataStore::Base]
62
+ # @return [self]
45
63
  def with_data_store(data_store)
46
64
  @data_store = data_store
47
65
  self
48
66
  end
49
67
 
68
+ # @yieldparam error [Exception]
69
+ # @return [self]
50
70
  def with_error_notifier(&error_notifier)
51
71
  @error_notifier = error_notifier
52
72
  self
53
73
  end
54
74
 
75
+ # @yieldparam error [Exception, nil]
76
+ # @return [self]
55
77
  def with_fallback(&fallback)
56
78
  @fallback = fallback
57
79
  self
58
80
  end
59
81
 
82
+ # @param notifiers [Array<Notifier::Base>]
83
+ # @return [self]
60
84
  def with_notifiers(notifiers)
61
85
  @notifiers = notifiers
62
86
  self
63
87
  end
64
88
 
89
+ # @param threshold [Fixnum]
90
+ # @return [self]
65
91
  def with_threshold(threshold)
66
92
  @threshold = threshold
67
93
  self
68
94
  end
69
95
 
96
+ # @param timeout [Float]
97
+ # @return [self]
70
98
  def with_timeout(timeout)
71
99
  @timeout = timeout
72
100
  self
@@ -3,6 +3,7 @@
3
3
  module Stoplight
4
4
  class Light
5
5
  module Runnable
6
+ # @return [String]
6
7
  def color
7
8
  failures, state = failures_and_state
8
9
  failure = failures.first
@@ -16,6 +17,7 @@ module Stoplight
16
17
  end
17
18
  end
18
19
 
20
+ # @raise [Error::RedLight]
19
21
  def run
20
22
  case color
21
23
  when Color::GREEN then run_green
@@ -2,7 +2,13 @@
2
2
 
3
3
  module Stoplight
4
4
  module Notifier
5
+ # @abstract
5
6
  class Base
7
+ # @param _light [Light]
8
+ # @param _from_color [String]
9
+ # @param _to_color [String]
10
+ # @param _error [Exception, nil]
11
+ # @return [String]
6
12
  def notify(_light, _from_color, _to_color, _error)
7
13
  fail NotImplementedError
8
14
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  module Stoplight
4
4
  module Notifier
5
+ # @see Base
5
6
  class HipChat < Base
6
7
  DEFAULT_OPTIONS = {
7
8
  color: 'purple',
@@ -9,11 +10,22 @@ module Stoplight
9
10
  notify: true
10
11
  }.freeze
11
12
 
13
+ # @return [Proc]
12
14
  attr_reader :formatter
15
+ # @return [::HipChat::Client]
13
16
  attr_reader :hip_chat
17
+ # @return [Hash{Symbol => Object}]
14
18
  attr_reader :options
19
+ # @return [String]
15
20
  attr_reader :room
16
21
 
22
+ # @param hip_chat [::HipChat::Client]
23
+ # @param room [String]
24
+ # @param formatter [Proc, nil]
25
+ # @param options [Hash{Symbol => Object}]
26
+ # @option options [String] :color
27
+ # @option options [String] :message_format
28
+ # @option options [Boolean] :notify
17
29
  def initialize(hip_chat, room, formatter = nil, options = {})
18
30
  @hip_chat = hip_chat
19
31
  @room = room
@@ -4,10 +4,15 @@ require 'stringio'
4
4
 
5
5
  module Stoplight
6
6
  module Notifier
7
+ # @see Base
7
8
  class IO < Base
9
+ # @return [Proc]
8
10
  attr_reader :formatter
11
+ # @return [::IO]
9
12
  attr_reader :io
10
13
 
14
+ # @param io [::IO]
15
+ # @param formatter [Proc, nil]
11
16
  def initialize(io, formatter = nil)
12
17
  @io = io
13
18
  @formatter = formatter || Default::FORMATTER
@@ -0,0 +1,5 @@
1
+ # coding: utf-8
2
+
3
+ module Stoplight
4
+ VERSION = Gem::Version.new('0.5.2')
5
+ end
@@ -0,0 +1,9 @@
1
+ # coding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Stoplight::VERSION do
6
+ it 'is a gem version' do
7
+ expect(described_class).to be_a(Gem::Version)
8
+ end
9
+ end
@@ -7,3 +7,15 @@ describe Stoplight do
7
7
  expect(described_class).to be_a(Module)
8
8
  end
9
9
  end
10
+
11
+ describe 'Stoplight' do
12
+ subject(:light) { Stoplight(name, &code) }
13
+ let(:name) { ('a'..'z').to_a.shuffle.join }
14
+ let(:code) { -> {} }
15
+
16
+ it 'creates a stoplight' do
17
+ expect(light).to be_a(Stoplight::Light)
18
+ expect(light.name).to eql(name)
19
+ expect(light.code).to eql(code)
20
+ end
21
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stoplight
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cameron Desautels
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2014-11-19 00:00:00.000000000 Z
13
+ date: 2015-02-13 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: benchmark-ips
@@ -74,56 +74,56 @@ dependencies:
74
74
  requirements:
75
75
  - - ~>
76
76
  - !ruby/object:Gem::Version
77
- version: '10.3'
77
+ version: '10.4'
78
78
  type: :development
79
79
  prerelease: false
80
80
  version_requirements: !ruby/object:Gem::Requirement
81
81
  requirements:
82
82
  - - ~>
83
83
  - !ruby/object:Gem::Version
84
- version: '10.3'
84
+ version: '10.4'
85
85
  - !ruby/object:Gem::Dependency
86
86
  name: redis
87
87
  requirement: !ruby/object:Gem::Requirement
88
88
  requirements:
89
89
  - - ~>
90
90
  - !ruby/object:Gem::Version
91
- version: '3.1'
91
+ version: '3.2'
92
92
  type: :development
93
93
  prerelease: false
94
94
  version_requirements: !ruby/object:Gem::Requirement
95
95
  requirements:
96
96
  - - ~>
97
97
  - !ruby/object:Gem::Version
98
- version: '3.1'
98
+ version: '3.2'
99
99
  - !ruby/object:Gem::Dependency
100
100
  name: rspec
101
101
  requirement: !ruby/object:Gem::Requirement
102
102
  requirements:
103
103
  - - ~>
104
104
  - !ruby/object:Gem::Version
105
- version: '3.1'
105
+ version: '3.2'
106
106
  type: :development
107
107
  prerelease: false
108
108
  version_requirements: !ruby/object:Gem::Requirement
109
109
  requirements:
110
110
  - - ~>
111
111
  - !ruby/object:Gem::Version
112
- version: '3.1'
112
+ version: '3.2'
113
113
  - !ruby/object:Gem::Dependency
114
114
  name: rubocop
115
115
  requirement: !ruby/object:Gem::Requirement
116
116
  requirements:
117
117
  - - ~>
118
118
  - !ruby/object:Gem::Version
119
- version: '0.27'
119
+ version: '0.29'
120
120
  type: :development
121
121
  prerelease: false
122
122
  version_requirements: !ruby/object:Gem::Requirement
123
123
  requirements:
124
124
  - - ~>
125
125
  - !ruby/object:Gem::Version
126
- version: '0.27'
126
+ version: '0.29'
127
127
  - !ruby/object:Gem::Dependency
128
128
  name: timecop
129
129
  requirement: !ruby/object:Gem::Requirement
@@ -181,6 +181,7 @@ files:
181
181
  - lib/stoplight/notifier/hip_chat.rb
182
182
  - lib/stoplight/notifier/io.rb
183
183
  - lib/stoplight/state.rb
184
+ - lib/stoplight/version.rb
184
185
  - spec/spec_helper.rb
185
186
  - spec/stoplight/color_spec.rb
186
187
  - spec/stoplight/data_store/base_spec.rb
@@ -197,6 +198,7 @@ files:
197
198
  - spec/stoplight/notifier/io_spec.rb
198
199
  - spec/stoplight/notifier_spec.rb
199
200
  - spec/stoplight/state_spec.rb
201
+ - spec/stoplight/version_spec.rb
200
202
  - spec/stoplight_spec.rb
201
203
  homepage: https://github.com/orgsync/stoplight
202
204
  licenses:
@@ -218,7 +220,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
218
220
  version: '0'
219
221
  requirements: []
220
222
  rubyforge_project:
221
- rubygems_version: 2.4.4
223
+ rubygems_version: 2.4.5
222
224
  signing_key:
223
225
  specification_version: 4
224
226
  summary: Traffic control for code.
@@ -239,5 +241,6 @@ test_files:
239
241
  - spec/stoplight/notifier/io_spec.rb
240
242
  - spec/stoplight/notifier_spec.rb
241
243
  - spec/stoplight/state_spec.rb
244
+ - spec/stoplight/version_spec.rb
242
245
  - spec/stoplight_spec.rb
243
246
  has_rdoc: