stoplight 0.5.1 → 0.5.2

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 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: