goodguide-pinglish 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 21349b68ac1102b95ac9e8e37ce9a8199af64d56
4
+ data.tar.gz: 65b356ff81337fa6e66d58547cec1eb8b1ff3fa5
5
+ SHA512:
6
+ metadata.gz: c6923231c568bcc36da5dc6569b57d23118fd64e14238a05b365409c2f82b189e3df45d8ba729b810e92f866cef66d59b83600b5e489b05b2afddfdad26cce05
7
+ data.tar.gz: 88ec461eeac036dcfde251f0b62fae7f3ad6a9cb5c17598528b9e20baae72b5d22743815208df81f323b40e7aab81b82f20b79956916f45be7bdd7143cdb0166
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ /*.gem
2
+ /.bundle
3
+ /Gemfile.lock
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source "https://rubygems.org"
2
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 John Barnette, Will Farrington, and contributors.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,119 @@
1
+ # Pinglish
2
+
3
+ A simple Rack middleware for checking application health. Pinglish
4
+ exposes a `/_ping` resource via HTTP `GET`, returning JSON that
5
+ conforms to the spec below.
6
+
7
+ ## The Spec
8
+
9
+ 0. The application __must__ respond to `GET /_ping` as an HTTP request.
10
+
11
+ 0. The request handler __should__ check the health of all services the
12
+ application depends on, answering questions like, "Can I query
13
+ agains my MySQL database," "Can I create/read keys in Redis," or "How
14
+ many docs are in my ElasticSearch index?"
15
+
16
+ 0. The response __must__ return within 29 seconds. This is one second
17
+ less than the default timeout for many monitoring services.
18
+
19
+ 0. The response __must__ return an `HTTP 200 OK` status code if all
20
+ health checks pass.
21
+
22
+ 0. The response __must__ return an `HTTP 503 SERVICE UNAVAILABLE`
23
+ status code if any health checks fail.
24
+
25
+ 0. The response __must__ be of Content-Type `application/json;
26
+ charset=UTF-8`.
27
+
28
+ 0. The response __must__ be valid JSON no matter what, even if JSON
29
+ serialization or other fundamental code fails.
30
+
31
+ 0. The response __must__ contain a `"status"` key set either to `"ok"`
32
+ or `"failures"`.
33
+
34
+ 0. The response __must__ contain a `"now"` key set to the current
35
+ server's time in seconds since epoch as a string.
36
+
37
+ 0. If the `"status"` key is set to `"failures"`, the response __may__
38
+ contain a `"failures"` key set to an Array of string names
39
+ representing failed checks.
40
+
41
+ 0. If the `"status"` key is set to `"failures"`, the response __may__
42
+ contain a `"timeouts"` key set to an Array of string names
43
+ representing checks that exceeded an implementation-specific
44
+ individual timeout.
45
+
46
+ 0. The response body __may__ contain any other top-level keys to
47
+ supply additional data about services the application consumes, but
48
+ all values must be strings, arrays of strings, or hashes where both
49
+ keys and values are strings.
50
+
51
+ ### An Example Response
52
+
53
+ ```javascript
54
+ {
55
+
56
+ // These two keys will always exist.
57
+
58
+ "now": "1359055102",
59
+ "status": "failures",
60
+
61
+ // This key may only exist when a named check has failed.
62
+
63
+ "failures": ["db"],
64
+
65
+ // This key may only exist when a named check exceeds its timeout.
66
+
67
+ "timeouts": ["really-long-check"],
68
+
69
+ // Keys like this may exist to provide extra information about
70
+ // healthy services, like the number of objects in an S3 bucket.
71
+
72
+ "s3": "127"
73
+ }
74
+ ```
75
+
76
+ ## The Middleware
77
+
78
+ ```ruby
79
+ require "pinglish"
80
+
81
+ use Pinglish do |ping|
82
+
83
+ # A single unnamed check is the simplest possible way to use
84
+ # Pinglish, and you'll probably never want combine it with other
85
+ # named checks. An unnamed check contributes to overall success or
86
+ # failure, but never adds additional data to the response.
87
+
88
+ ping.check do
89
+ App.healthy?
90
+ end
91
+
92
+ # A named check like this can provide useful summary information
93
+ # when it succeeds. In this case, a top-level "db" key will appear
94
+ # in the response containing the number of items in the database. If
95
+ # a check returns nil, no key will be added to the response.
96
+
97
+ ping.check :db do
98
+ App.db.items.size
99
+ end
100
+
101
+ # By default, checks time out after one second. You can override
102
+ # this with the :timeout option, but be aware that no combination of
103
+ # checks is ever allowed to exceed the overall 29 second limit.
104
+
105
+ ping.check :long, :timeout => 5 do
106
+ App.dawdle
107
+ end
108
+
109
+ # Signal check failure by raising an exception. Any exception will do.
110
+ ping.check :fails do
111
+ raise "Everything's ruined."
112
+ end
113
+
114
+ # Additionally, any check that returns false is counted as a failure.
115
+ ping.check :false_fails do
116
+ false
117
+ end
118
+ end
119
+ ```
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |gem|
4
+ gem.name = "goodguide-pinglish"
5
+ gem.version = "1.0.0"
6
+ gem.authors = ["John Barnette", "Will Farrington"]
7
+ gem.email = ["jbarnette@github.com", "wfarr@github.com"]
8
+ gem.description = "A simple Rack middleware for checking app health."
9
+ gem.summary = "/_ping your way to freedom."
10
+ gem.homepage = "https://github.com/goodguide/pinglish"
11
+
12
+ gem.files = `git ls-files`.split($/)
13
+ gem.test_files = gem.files.grep(/^test/)
14
+ gem.require_paths = ["lib"]
15
+
16
+ gem.add_dependency "rack"
17
+ gem.add_development_dependency "minitest", "~> 4.5"
18
+ gem.add_development_dependency "rack-test", "~> 0.6"
19
+ end
@@ -0,0 +1,21 @@
1
+ class Pinglish
2
+ class Check
3
+ attr_reader :group
4
+ attr_reader :name
5
+ attr_reader :timeout
6
+
7
+ def initialize(name, options = nil, &block)
8
+ options ||= {}
9
+ @group = options[:group]
10
+ @name = name
11
+ @timeout = options[:timeout] || 1
12
+ @block = block
13
+ end
14
+
15
+ # Call this check's behavior, returning the result of the block.
16
+
17
+ def call(*args, &block)
18
+ @block.call *args, &block
19
+ end
20
+ end
21
+ end
data/lib/pinglish.rb ADDED
@@ -0,0 +1,146 @@
1
+ require "json"
2
+ require "pinglish/check"
3
+ require "rack/request"
4
+ require "timeout"
5
+
6
+ # This Rack app provides an endpoint for configurable
7
+ # system health checks. It's intended to be consumed by machines.
8
+
9
+ class Pinglish
10
+
11
+ # The HTTP headers sent for every response.
12
+ HEADERS = {
13
+ "Content-Type" => "application/json; charset=UTF-8"
14
+ }
15
+
16
+ # Raised when a check exceeds its timeout.
17
+ class TooLong < RuntimeError; end
18
+
19
+ # Create a new instance of the app, with optional parameter `:max` timeout in seconds (default: `29`); yields itself to an optional block for configuring checks.
20
+ def initialize(options=nil, &block)
21
+ options ||= {}
22
+
23
+ @checks = {}
24
+ @max = options[:max] || 29 # seconds
25
+
26
+ yield self if block_given?
27
+ end
28
+
29
+ def call(env)
30
+ request = Rack::Request.new(env)
31
+
32
+ begin
33
+ timeout @max do
34
+ results = {}
35
+
36
+ selected_checks(request.params).each do |check|
37
+ begin
38
+ timeout(check.timeout) do
39
+ results[check.name] = check.call
40
+ end
41
+ rescue => e
42
+ results[check.name] = e
43
+ end
44
+ end
45
+
46
+ failed = results.values.any? { |v| failure? v }
47
+ http_status = failed ? 503 : 200
48
+ text_status = failed ? "failures" : "ok"
49
+
50
+ data = {
51
+ :now => Time.now.to_i.to_s,
52
+ :status => text_status
53
+ }
54
+
55
+ results.each do |name, value|
56
+ if failure?(value)
57
+ # If a check fails its name is added to a `failures` array.
58
+ # If the check failed because it timed out, its name is
59
+ # added to a `timeouts` array instead.
60
+
61
+ key = timeout?(value) ? :timeouts : :failures
62
+ (data[key] ||= []) << name
63
+
64
+ if key == :failures and value.is_a?(Exception)
65
+ data[name] = {
66
+ state: :error,
67
+ exception: value.class.name,
68
+ message: value.message,
69
+ }
70
+ end
71
+
72
+ elsif value
73
+ # If the check passed and returned a value, the stringified
74
+ # version of the value is returned under the `name` key.
75
+
76
+ data[name] = value
77
+ end
78
+ end
79
+
80
+ [http_status, HEADERS, [JSON.generate(data)]]
81
+ end
82
+
83
+ rescue Exception => ex
84
+ # Something catastrophic happened. We can't even run the checks
85
+ # and render a JSON response. Fall back on a pre-rendered string
86
+ # and interpolate the current epoch time.
87
+
88
+ now = Time.now.to_i.to_s
89
+
90
+ body = <<-EOF.gsub(/^ {6}/, '')
91
+ {
92
+ "status": "failures",
93
+ "now": "#{now}",
94
+ "error": {
95
+ "class": "#{ex.class.name}",
96
+ "message": "#{ex.message.tr('"', '')}"
97
+ }
98
+ }
99
+ EOF
100
+
101
+ [500, HEADERS, [body]]
102
+ end
103
+ end
104
+
105
+ def selected_checks(params)
106
+ if (selected = params['checks'])
107
+ selected = selected.split(',').map(&:to_sym)
108
+ return @checks.values_at(*selected).compact
109
+ end
110
+ @checks.values
111
+ end
112
+
113
+ # Add a new check with optional `name`. A `:timeout` option can be
114
+ # specified in seconds for checks that might take longer than the
115
+ # one second default. A previously added check with the same name
116
+ # will be replaced.
117
+
118
+ def check(name = :default, options = nil, &block)
119
+ @checks[name.to_sym] = Check.new(name, options, &block)
120
+ end
121
+
122
+ # Does `value` represent a check failure? This default
123
+ # implementation returns `true` for any value that is an Exception or false.
124
+ # Subclasses can override this method for different behavior.
125
+
126
+ def failure?(value)
127
+ value.is_a?(Exception) || value == false
128
+ end
129
+
130
+ # Raise Pinglish::TooLong after `seconds` has elapsed. This default
131
+ # implementation uses Ruby's built-in Timeout class. Subclasses can
132
+ # override this method for different behavior, but any new
133
+ # implementation must raise Pinglish::TooLong when the timeout is
134
+ # exceeded or override `timeout?` appropriately.
135
+
136
+ def timeout(seconds, &block)
137
+ Timeout.timeout seconds, Pinglish::TooLong, &block
138
+ end
139
+
140
+ # Does `value` represent a check timeout? Returns `true` for any
141
+ # value that is an instance of Pinglish::TooLong.
142
+
143
+ def timeout?(value)
144
+ value.is_a? Pinglish::TooLong
145
+ end
146
+ end
data/script/bootstrap ADDED
@@ -0,0 +1,9 @@
1
+ #!/bin/sh
2
+ # Make sure local development dependencies are satisfied.
3
+
4
+ set -e
5
+
6
+ cd $(dirname "$0")/..
7
+ rm -rf .bundle/config
8
+
9
+ bundle install --path .bundle --binstubs .bundle/binstubs --quiet "$@"
data/script/release ADDED
@@ -0,0 +1,38 @@
1
+ #!/bin/sh
2
+ # Tag and push a release.
3
+
4
+ set -e
5
+
6
+ # Make sure we're in the project root.
7
+
8
+ cd $(dirname "$0")/..
9
+
10
+ # Build a new gem archive.
11
+
12
+ rm -rf pinglish-*.gem
13
+ gem build -q pinglish.gemspec
14
+
15
+ # Make sure we're on the master branch.
16
+
17
+ (git branch | grep -q '* master') || {
18
+ echo "Only release from the master branch."
19
+ exit 1
20
+ }
21
+
22
+ # Figure out what version we're releasing.
23
+
24
+ tag=v`ls pinglish-*.gem | sed 's/^pinglish-\(.*\)\.gem$/\1/'`
25
+
26
+ # Make sure we haven't released this version before.
27
+
28
+ git fetch -t origin
29
+
30
+ (git tag -l | grep -q "$tag") && {
31
+ echo "Whoops, there's already a '${tag}' tag."
32
+ exit 1
33
+ }
34
+
35
+ # Tag it and bag it.
36
+
37
+ gem push pinglish-*.gem && git tag "$tag" &&
38
+ git push origin master && git push origin "$tag"
data/script/test ADDED
@@ -0,0 +1,9 @@
1
+ #!/bin/sh
2
+ # Run the tests.
3
+
4
+ set -e
5
+
6
+ cd $(dirname "$0")/..
7
+
8
+ script/bootstrap && ruby -I lib -I test -rubygems \
9
+ -e 'require "bundler/setup"; Dir["test/**/*_test.rb"].each { |f| load f }' "$@"
@@ -0,0 +1,23 @@
1
+ require "helper"
2
+
3
+ class PinglishCheckTest < MiniTest::Unit::TestCase
4
+ def test_initialize
5
+ check = Pinglish::Check.new(:db)
6
+ assert_equal :db, check.name
7
+ end
8
+
9
+ def test_initialize_default_timeout
10
+ check = Pinglish::Check.new(:db)
11
+ assert_equal 1, check.timeout
12
+ end
13
+
14
+ def test_initialize_override_timeout
15
+ check = Pinglish::Check.new(:db, :timeout => 2)
16
+ assert_equal 2, check.timeout
17
+ end
18
+
19
+ def test_call
20
+ check = Pinglish::Check.new(:db) { :result_of_block }
21
+ assert_equal :result_of_block, check.call
22
+ end
23
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,2 @@
1
+ require "minitest/autorun"
2
+ require "pinglish"
@@ -0,0 +1,262 @@
1
+ require "helper"
2
+ require "rack/test"
3
+
4
+ class PinglishTest < MiniTest::Unit::TestCase
5
+ FakeApp = lambda { |env| [200, {}, ["fake"]] }
6
+
7
+ def build_app(*args, &block)
8
+ Rack::Builder.new do |builder|
9
+ builder.map '/_ping' do
10
+ run Pinglish.new(*args, &block)
11
+ end
12
+ builder.run FakeApp
13
+ end
14
+ end
15
+
16
+ def build_app_that_explodes(*args, &block)
17
+ Rack::Builder.new do |builder|
18
+ builder.map '/_ping' do
19
+ run Pinglish.new(*args, &block)
20
+ end
21
+ builder.run lambda { |env| raise "boom" }
22
+ end
23
+ end
24
+
25
+ def test_with_non_matching_request_path_and_exception
26
+ app = build_app_that_explodes
27
+ session = Rack::Test::Session.new(app)
28
+
29
+ assert_raises RuntimeError do
30
+ session.get "/something"
31
+ end
32
+ end
33
+
34
+ def test_with_defaults
35
+ app = build_app
36
+
37
+ session = Rack::Test::Session.new(app)
38
+ session.get "/_ping"
39
+ assert_equal 200, session.last_response.status
40
+ assert_equal "application/json; charset=UTF-8",
41
+ session.last_response.content_type
42
+
43
+ json = JSON.load(session.last_response.body)
44
+ assert json.key?("now")
45
+ assert_equal "ok", json["status"]
46
+ end
47
+
48
+ def test_with_good_check
49
+ app = build_app do |ping|
50
+ ping.check(:db) { :up_and_at_em }
51
+ ping.check(:queue) { :pushin_and_poppin }
52
+ end
53
+
54
+ session = Rack::Test::Session.new(app)
55
+ session.get "/_ping"
56
+
57
+ assert_equal "application/json; charset=UTF-8",
58
+ session.last_response.content_type
59
+
60
+ json = JSON.load(session.last_response.body)
61
+ assert json.key?("now")
62
+ assert_equal "ok", json["status"]
63
+ assert_equal "up_and_at_em", json["db"]
64
+ assert_equal "pushin_and_poppin", json["queue"]
65
+ end
66
+
67
+ def test_with_unnamed_check
68
+ app = build_app do |ping|
69
+ ping.check { :yohoho }
70
+ end
71
+
72
+ session = Rack::Test::Session.new(app)
73
+ session.get "/_ping"
74
+
75
+ assert_equal "application/json; charset=UTF-8",
76
+ session.last_response.content_type
77
+
78
+ json = JSON.load(session.last_response.body)
79
+ assert json.key?("now")
80
+ assert_equal "ok", json["status"]
81
+ assert_equal "yohoho", json["default"]
82
+ end
83
+
84
+ def test_with_unnamed_check_that_raises
85
+ app = build_app do |ping|
86
+ ping.check { raise "nooooope" }
87
+ end
88
+
89
+ session = Rack::Test::Session.new(app)
90
+ session.get "/_ping"
91
+
92
+ assert_equal "application/json; charset=UTF-8",
93
+ session.last_response.content_type
94
+
95
+ json = JSON.load(session.last_response.body)
96
+ assert json.key?("now")
97
+ assert_equal 'failures', json["status"]
98
+ assert_equal ['default'], json["failures"]
99
+ assert_equal({
100
+ 'state' => 'error',
101
+ 'exception' => 'RuntimeError',
102
+ 'message' => 'nooooope'
103
+ }, json["default"])
104
+ end
105
+
106
+
107
+ def test_with_check_that_raises
108
+ app = build_app do |ping|
109
+ ping.check(:db) { :ok }
110
+ ping.check(:raise) { raise "nooooope" }
111
+ end
112
+
113
+ session = Rack::Test::Session.new(app)
114
+ session.get "/_ping"
115
+
116
+ assert_equal 503, session.last_response.status
117
+ assert_equal "application/json; charset=UTF-8",
118
+ session.last_response.content_type
119
+
120
+ json = JSON.load(session.last_response.body)
121
+ assert json.key?("now")
122
+ assert_equal "failures", json["status"]
123
+ assert_equal ['raise'], json["failures"]
124
+ assert_equal({
125
+ 'state' => 'error',
126
+ 'exception' => 'RuntimeError',
127
+ 'message' => 'nooooope'
128
+ }, json["raise"])
129
+ end
130
+
131
+ def test_with_check_that_returns_false
132
+ app = build_app do |ping|
133
+ ping.check(:db) { :ok }
134
+ ping.check(:fail) { false }
135
+ end
136
+
137
+ session = Rack::Test::Session.new(app)
138
+ session.get "/_ping"
139
+
140
+ assert_equal 503, session.last_response.status
141
+ assert_equal "application/json; charset=UTF-8",
142
+ session.last_response.content_type
143
+
144
+ json = JSON.load(session.last_response.body)
145
+ assert json.key?("now")
146
+ assert_equal "failures", json["status"]
147
+ assert_equal ["fail"], json["failures"]
148
+ assert_equal false, json.key?("fail")
149
+ end
150
+
151
+ def test_with_check_that_times_out
152
+ app = build_app do |ping|
153
+ ping.check(:db) { :ok }
154
+ ping.check(:long, :timeout => 0.001) { sleep 0.003 }
155
+ end
156
+
157
+ session = Rack::Test::Session.new(app)
158
+ session.get "/_ping"
159
+
160
+ assert_equal 503, session.last_response.status
161
+ assert_equal "application/json; charset=UTF-8",
162
+ session.last_response.content_type
163
+
164
+ json = JSON.load(session.last_response.body)
165
+ assert json.key?("now")
166
+ assert_equal "failures", json["status"]
167
+ assert_equal ["long"], json["timeouts"]
168
+ end
169
+
170
+ def test_with_checks_taking_more_than_max
171
+ app = build_app(:max => 0.001) do |ping|
172
+ ping.check(:long) { sleep 0.003 }
173
+ end
174
+
175
+ session = Rack::Test::Session.new(app)
176
+ session.get "/_ping"
177
+
178
+ assert_equal 503, session.last_response.status
179
+ assert_equal "application/json; charset=UTF-8",
180
+ session.last_response.content_type
181
+
182
+ json = JSON.load(session.last_response.body)
183
+ assert json.key?("now")
184
+ assert_equal "failures", json["status"]
185
+ assert_equal ['long'], json["timeouts"]
186
+ end
187
+
188
+ def test_with_script_name
189
+ app = build_app
190
+
191
+ session = Rack::Test::Session.new(app)
192
+ session.get "/_ping", {}, "SCRIPT_NAME" => "/myapp"
193
+ assert_equal 200, session.last_response.status
194
+ assert_equal "application/json; charset=UTF-8",
195
+ session.last_response.content_type
196
+
197
+ json = JSON.load(session.last_response.body)
198
+ assert json.key?("now")
199
+ assert_equal "ok", json["status"]
200
+ end
201
+
202
+ def test_with_selective_checks
203
+ app = build_app do |ping|
204
+ ping.check(:db) { :ok }
205
+ ping.check(:foo) { :bar }
206
+ ping.check(:long, :timeout => 0.001) { sleep 0.003 }
207
+ end
208
+
209
+ session = Rack::Test::Session.new(app)
210
+ session.get "/_ping?checks=db,foo"
211
+
212
+ assert_equal 200, session.last_response.status
213
+ assert_equal "application/json; charset=UTF-8",
214
+ session.last_response.content_type
215
+
216
+ json = JSON.load(session.last_response.body)
217
+ assert json.key?("now")
218
+ assert_equal "ok", json["status"]
219
+ assert_equal false, json.key?("timeouts")
220
+ assert_equal false, json.key?("failures")
221
+ assert_equal 'ok', json['db']
222
+ assert_equal 'bar', json['foo']
223
+ end
224
+
225
+ def test_check_without_name
226
+ pinglish = Pinglish.new(FakeApp)
227
+ check = pinglish.check { :ok }
228
+ assert_instance_of Pinglish::Check, check
229
+ end
230
+
231
+ def test_check_with_name
232
+ pinglish = Pinglish.new(FakeApp)
233
+ check = pinglish.check(:db) { :ok }
234
+ assert_instance_of Pinglish::Check, check
235
+ assert_equal :db, check.name
236
+ end
237
+
238
+ def test_failure_boolean
239
+ pinglish = Pinglish.new(FakeApp)
240
+
241
+ assert pinglish.failure?(Exception.new)
242
+ assert pinglish.failure?(false)
243
+
244
+ refute pinglish.failure?(true)
245
+ refute pinglish.failure?(:ok)
246
+ end
247
+
248
+ def test_timeout
249
+ pinglish = Pinglish.new(FakeApp)
250
+
251
+ assert_raises Pinglish::TooLong do
252
+ pinglish.timeout(0.001) { sleep 0.003 }
253
+ end
254
+ end
255
+
256
+ def test_timeout_boolean
257
+ pinglish = Pinglish.new(FakeApp)
258
+
259
+ assert pinglish.timeout?(Pinglish::TooLong.new)
260
+ refute pinglish.timeout?(Exception.new)
261
+ end
262
+ end
metadata ADDED
@@ -0,0 +1,104 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: goodguide-pinglish
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - John Barnette
8
+ - Will Farrington
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2015-04-25 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rack
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: '0'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: '0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: minitest
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '4.5'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '4.5'
42
+ - !ruby/object:Gem::Dependency
43
+ name: rack-test
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: '0.6'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: '0.6'
56
+ description: A simple Rack middleware for checking app health.
57
+ email:
58
+ - jbarnette@github.com
59
+ - wfarr@github.com
60
+ executables: []
61
+ extensions: []
62
+ extra_rdoc_files: []
63
+ files:
64
+ - ".gitignore"
65
+ - Gemfile
66
+ - LICENSE
67
+ - README.md
68
+ - goodguide-pinglish.gemspec
69
+ - lib/pinglish.rb
70
+ - lib/pinglish/check.rb
71
+ - script/bootstrap
72
+ - script/release
73
+ - script/test
74
+ - test/check_test.rb
75
+ - test/helper.rb
76
+ - test/pinglish_test.rb
77
+ homepage: https://github.com/goodguide/pinglish
78
+ licenses: []
79
+ metadata: {}
80
+ post_install_message:
81
+ rdoc_options: []
82
+ require_paths:
83
+ - lib
84
+ required_ruby_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ requirements: []
95
+ rubyforge_project:
96
+ rubygems_version: 2.2.2
97
+ signing_key:
98
+ specification_version: 4
99
+ summary: "/_ping your way to freedom."
100
+ test_files:
101
+ - test/check_test.rb
102
+ - test/helper.rb
103
+ - test/pinglish_test.rb
104
+ has_rdoc: