goodguide-pinglish 1.0.0

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