rx-healthcheck 0.1.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
+ SHA256:
3
+ metadata.gz: 51191dafecd2e8ad24a88a3c60a44f49618f7983ded633bf58df1f482583c6a7
4
+ data.tar.gz: c283c8507f67d1e1d6012e8a94b33fb4ba17fd0724bde9e523388b28efa5b0ba
5
+ SHA512:
6
+ metadata.gz: 7f79992064d97c64192b55378a2d5477fe11cfbfbf3aad28b92236bcaa5bcd7bb247b0df885d00c6eec17146f23620822312c39068e4dbb391d4d287a36da30f
7
+ data.tar.gz: 9e4cc0de75b8b3bf88e9c4588706ecd1315051f558779e53150c615e581f8b04363731b3527134a8a35044564fd08226d14c94e3c7ba3e17491dfd7acd604291
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in rx.gemspec
6
+ gemspec
7
+
8
+ gem "rake", "~> 13.0"
9
+
10
+ gem "minitest", "~> 5.0"
data/Gemfile.lock ADDED
@@ -0,0 +1,29 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ rx (0.1.0)
5
+ simplecov (= 0.21.2)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ docile (1.4.0)
11
+ minitest (5.14.4)
12
+ rake (13.0.3)
13
+ simplecov (0.21.2)
14
+ docile (~> 1.1)
15
+ simplecov-html (~> 0.11)
16
+ simplecov_json_formatter (~> 0.1)
17
+ simplecov-html (0.12.3)
18
+ simplecov_json_formatter (0.1.3)
19
+
20
+ PLATFORMS
21
+ x86_64-linux
22
+
23
+ DEPENDENCIES
24
+ minitest (~> 5.0)
25
+ rake (~> 13.0)
26
+ rx!
27
+
28
+ BUNDLED WITH
29
+ 2.2.11
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2021 Zach Pendleton
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,73 @@
1
+ # Rx
2
+
3
+ Rx is a Rack middleware that provides tiered health checks to any Rack application, including Rails-based apps.
4
+
5
+ ## Tiered Health Checks
6
+
7
+ What is a tiered health check? I'm glad you asked! Health checks serve different purposes:
8
+
9
+ - Some are used by load balancers to ensure that a server is capable of serving traffic
10
+ - Some are used by other applications to verify the health of your service as a dependency
11
+ - Some are used by customers or status pages to determine uptime
12
+
13
+ These use cases are all similar, but may require different levels of verification. One may require your service to just return 200, while another may need to check connectivity to the database, cache, or external services.
14
+
15
+ Rx provides three levels of health checks:
16
+
17
+ 1. `/liveness`: A health check that determines if the server is running.
18
+ 2. `/readiness`: Readiness checks determine if critical, dependent services are running (think a database or cache)
19
+ 3. `/deep`: A health check that walks your entire dependency tree, checking other critical and secondary services.
20
+
21
+ ### Rails Applications
22
+
23
+ Add `rx` to your Gemfile, and then create a new initializer with something like this:
24
+
25
+ ```ruby
26
+ Rails.application.config.middleware.insert(
27
+ Rx::Middleware,
28
+ liveness: [Rx::Check::FileSystemCheck.new],
29
+ readiness: [
30
+ Rx::Check::FileSystemCheck.new,
31
+ Rx::Check::ActiveRecordCheck.new,
32
+ Rx::Check::HttpCheck.new("http://example.com"),
33
+ Rx::Check::GenericCheck.new(-> { $redis.ping == "PONG" }, "redis")],
34
+ deep_critical: [Rx::Check::HttpCheck.new("http://criticalservice.com/health")],
35
+ deep_secondary: [Rx::Check::HttpCheck.new("http://otherservice.com/health-check")]
36
+ )
37
+ ```
38
+
39
+ ### Configuring Dependencies
40
+
41
+ Now that you're running `rx`, you will need to configure which dependencies it tests in each health check. You can do this by passing `Rx::Check` objects to the middleware. `rx` ships with a number of standard checks:
42
+
43
+ - Filesystem health
44
+ - ActiveRecord
45
+ - HTTP
46
+ - Generic Check
47
+
48
+ In addition to the stock checks, you may create your own by copying an existing check
49
+ and modifying it (though it's probably simpler to just use GenericCheck).
50
+
51
+ `RX::Middleware` accepts the following named parameters as configuration:
52
+
53
+ ```ruby
54
+ liveness: [],
55
+ readiness: [],
56
+ deep_critical: [],
57
+ deep_secondary: []
58
+ ```
59
+
60
+ Each collection must contain 0 or more `Rx::Check` objects. Those checks will be performed when the health check is queried. Deep checks will always also run the readiness checks.
61
+
62
+ ## Contributing
63
+
64
+ Bug reports and pull requests are welcome on GitHub at https://github.com/zachpendleton/rx.
65
+
66
+ Some tips for developing the gem locally:
67
+
68
+ * Tests can be run by calling `rake`
69
+ * You can point your Rails app to a local gem by adding a `path` option to your Gemfile, a la `gem "rx", path: "path/to/rx" (though you _will_ need to restart Rails whenever you change the gem).
70
+
71
+ ## License
72
+
73
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rake/testtask"
5
+
6
+ Rake::TestTask.new(:test) do |t|
7
+ t.libs << "test"
8
+ t.libs << "lib"
9
+ t.test_files = FileList["test/**/*_test.rb"]
10
+ end
11
+
12
+ task default: :test
data/bin/console ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "rx"
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ require "irb"
15
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/lib/rx.rb ADDED
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "rx/version"
4
+ require_relative "rx/middleware"
5
+ require_relative "rx/cache/in_memory_cache"
6
+ require_relative "rx/cache/no_op_cache"
7
+ require_relative "rx/check/active_record_check"
8
+ require_relative "rx/check/file_system_check"
9
+ require_relative "rx/check/generic_check"
10
+ require_relative "rx/check/http_check"
11
+ require_relative "rx/check/result"
12
+ require_relative "rx/concurrent/future"
13
+ require_relative "rx/concurrent/thread_pool"
14
+ require_relative "rx/util/heap"
15
+
16
+ module Rx
17
+ class Error < StandardError; end
18
+ # Your code goes here...
19
+ end
@@ -0,0 +1,51 @@
1
+ require_relative "../util/heap"
2
+
3
+ module Rx
4
+ module Cache
5
+ class InMemoryCache
6
+ def initialize
7
+ @heap = Rx::Util::Heap.new do |a, b|
8
+ a[1] < b[1]
9
+ end
10
+ @lock = Mutex.new
11
+ @map = Hash.new
12
+ end
13
+
14
+ def cache(k, expires_in = 60)
15
+ if value = get(k)
16
+ return value
17
+ end
18
+
19
+ value = yield
20
+ put(k, value, expires_in)
21
+ value
22
+ end
23
+
24
+ def get(k)
25
+ clean!
26
+
27
+ lock.synchronize do
28
+ map[k]
29
+ end
30
+ end
31
+
32
+ def put(k, v, expires_in = 60)
33
+ lock.synchronize do
34
+ map[k] = v
35
+ heap << [k, Time.now + expires_in]
36
+ end
37
+ end
38
+
39
+ private
40
+ attr_reader :heap, :lock, :map
41
+
42
+ def clean!
43
+ lock.synchronize do
44
+ while !heap.peek.nil? && heap.peek[1] < Time.now
45
+ map.delete(heap.pop[0])
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,17 @@
1
+ module Rx
2
+ module Cache
3
+ class NoOpCache
4
+ def cache(k, expires_in = 60)
5
+ yield
6
+ end
7
+
8
+ def get(k)
9
+ nil
10
+ end
11
+
12
+ def put(k, v, expires_in = 60)
13
+ nil
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,27 @@
1
+ module Rx
2
+ module Check
3
+ class ActiveRecordCheck
4
+ attr_reader :name
5
+
6
+ def initialize(name = "activerecord")
7
+ @name = name
8
+ end
9
+
10
+ def check
11
+ Result.from(name) do
12
+ unless activerecord_defined?
13
+ raise StandardError.new("Undefined class ActiveRecord::Base")
14
+ end
15
+
16
+ ActiveRecord::Base.connection.active?
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def activerecord_defined?
23
+ defined?(ActiveRecord::Base)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,22 @@
1
+ module Rx
2
+ module Check
3
+ class FileSystemCheck
4
+ FILENAME = "rx".freeze
5
+
6
+ attr_reader :name
7
+
8
+ def initialize(name = "fs")
9
+ @name = name
10
+ end
11
+
12
+ def check
13
+ Result.from(name) do
14
+ !!Tempfile.open(FILENAME) do |f|
15
+ f.write("ok")
16
+ f.flush
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ module Rx
2
+ module Check
3
+ class GenericCheck
4
+ attr_reader :name
5
+
6
+ def initialize(callable, name = "generic")
7
+ @callable = callable
8
+ @name = name
9
+ end
10
+
11
+ def check
12
+ Result.from(name) do
13
+ callable.call
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ attr_reader :callable
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,37 @@
1
+ require "uri"
2
+
3
+ module Rx
4
+ module Check
5
+ class HttpCheck
6
+ attr_reader :name
7
+
8
+ def initialize(url, name = "http")
9
+ @url = URI(url)
10
+ @name = name
11
+ end
12
+
13
+ def check
14
+ Result.from(name) do
15
+ http = Net::HTTP.new(url.host, url.port)
16
+ http.read_timeout = 1
17
+ http.use_ssl = url.scheme == "https"
18
+
19
+ response = http.request(Net::HTTP::Get.new(path))
20
+ response.code == "200"
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ attr_reader :url
27
+
28
+ def path
29
+ path = url.path == "" ? "/" : url.path
30
+ path = "#{path}?#{url.query}" if url.query
31
+ path = "#{path}##{url.fragment}" if url.fragment
32
+
33
+ path
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,34 @@
1
+ module Rx
2
+ module Check
3
+ class Result
4
+ def self.from(check_name)
5
+ start_at = Time.now
6
+ err = nil
7
+ result = false
8
+
9
+ begin
10
+ result = yield
11
+ rescue StandardError => ex
12
+ err = ex
13
+ end
14
+
15
+ end_at = Time.now
16
+
17
+ Result.new(check_name, result, ((end_at - start_at) * 1000).round(2), err)
18
+ end
19
+
20
+ attr_reader :name, :timing, :error
21
+
22
+ def initialize(name, ok, timing, error)
23
+ @name = name
24
+ @ok = ok
25
+ @timing = timing
26
+ @error = error
27
+ end
28
+
29
+ def ok?
30
+ @ok
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,71 @@
1
+ require "thread"
2
+ require_relative "thread_pool"
3
+
4
+ module Rx
5
+ module Concurrent
6
+ class Future
7
+ @@pool = ThreadPool.new.start
8
+
9
+ ALLOWED_STATES = %i[pending in_progress completed failed]
10
+
11
+ attr_reader :error
12
+
13
+ def self.execute(&block)
14
+ Future.new(&block).execute
15
+ end
16
+
17
+ def initialize(&block)
18
+ @channel = Queue.new
19
+ @state = :pending
20
+ @work = block
21
+ end
22
+
23
+ def completed?
24
+ state == :completed
25
+ end
26
+
27
+ def execute
28
+ @state = :in_progress
29
+ pool.submit do
30
+ begin
31
+ channel << work.call
32
+ @state = :completed
33
+ rescue StandardError => ex
34
+ @error = ex
35
+ @state = :failed
36
+ channel.close
37
+ end
38
+ end
39
+
40
+ self
41
+ end
42
+
43
+ def failed?
44
+ state == :failed
45
+ end
46
+
47
+ def in_progress?
48
+ state == :in_progress
49
+ end
50
+
51
+ def pending?
52
+ state == :pending
53
+ end
54
+
55
+ def value
56
+ if (completed? || failed?) && channel.empty?
57
+ return @value
58
+ end
59
+
60
+ @value = channel.pop
61
+ end
62
+
63
+ private
64
+ attr_reader :channel, :state, :work
65
+
66
+ def pool
67
+ @@pool
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,53 @@
1
+ require "thread"
2
+
3
+ module Rx
4
+ module Concurrent
5
+ class ThreadPool
6
+ def initialize(size = Etc.nprocessors)
7
+ @pool = []
8
+ @size = size
9
+ end
10
+
11
+ def shutdown
12
+ return unless started?
13
+
14
+ queue.close
15
+ pool.map(&:join)
16
+ pool.clear
17
+ end
18
+
19
+ def start
20
+ return if started?
21
+
22
+ @queue = Queue.new
23
+ size.times { pool << Thread.new(&worker) }
24
+
25
+ self
26
+ end
27
+
28
+ def started?
29
+ pool.map(&:alive?).any?
30
+ end
31
+
32
+ def submit(&block)
33
+ return unless started?
34
+ queue << block
35
+ end
36
+
37
+ private
38
+ attr_reader :pool, :queue, :size
39
+
40
+ def worker
41
+ -> {
42
+ while job = queue.pop
43
+ begin
44
+ job.call
45
+ rescue StandardError => _
46
+ # do nothing
47
+ end
48
+ end
49
+ }
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,95 @@
1
+ require "json"
2
+
3
+ module Rx
4
+ class Middleware
5
+ DEFAULT_OPTIONS = {
6
+ cache: true
7
+ }.freeze
8
+
9
+ def initialize(app,
10
+ liveness: [Rx::Check::FileSystemCheck.new],
11
+ readiness: [Rx::Check::FileSystemCheck.new],
12
+ deep_critical: [],
13
+ deep_secondary: [],
14
+ options: {})
15
+ @app = app
16
+ @options = DEFAULT_OPTIONS.merge(options)
17
+ @cache = cache_factory(self.options)
18
+
19
+ @liveness_checks = liveness
20
+ @readiness_checks = readiness
21
+ @deep_critical_checks = deep_critical
22
+ @deep_secondary_checks = deep_secondary
23
+ end
24
+
25
+ def call(env)
26
+ unless health_check_request?(env)
27
+ return app.call(env)
28
+ end
29
+
30
+ case env["REQUEST_PATH"]
31
+ when "/liveness"
32
+ ok = check_to_component(liveness_checks).map { |x| x[:status] == 200 }.all?
33
+ liveness_response(ok)
34
+ when "/readiness"
35
+ readiness_response(check_to_component(readiness_checks))
36
+ when "/deep"
37
+ @cache.cache("deep") do
38
+ readiness = check_to_component(readiness_checks)
39
+ critical = check_to_component(deep_critical_checks)
40
+ secondary = check_to_component(deep_secondary_checks)
41
+
42
+ deep_response(readiness, critical, secondary)
43
+ end
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ attr_reader :app, :liveness_checks, :readiness_checks, :deep_critical_checks,
50
+ :deep_secondary_checks, :options
51
+
52
+ def cache_factory(options)
53
+ unless options[:cache]
54
+ return Rx::Cache::NoOpCache.new
55
+ end
56
+
57
+ Rx::Cache::InMemoryCache.new
58
+ end
59
+
60
+ def health_check_request?(env)
61
+ %w[/liveness /readiness /deep].include?(env["REQUEST_PATH"])
62
+ end
63
+
64
+ def liveness_response(is_ok)
65
+ [is_ok ? 200 : 503, {}, []]
66
+ end
67
+
68
+ def readiness_response(components)
69
+ status = components.map { |x| x[:status] == 200 }.all? ? 200 : 503
70
+
71
+ [
72
+ status,
73
+ {"content-type" => "application/json"},
74
+ [JSON.dump({status: status, components: components})]
75
+ ]
76
+ end
77
+
78
+ def deep_response(readiness, critical, secondary)
79
+ status = (readiness.map { |x| x[:status] == 200 } + critical.map { |x| x[:status] == 200 }).all? ? 200 : 503
80
+
81
+ [
82
+ status,
83
+ {"content-type" => "application/json"},
84
+ [JSON.dump(status: status, readiness: readiness, critical: critical, secondary: secondary)]
85
+ ]
86
+ end
87
+
88
+ def check_to_component(check)
89
+ Array(check)
90
+ .map { |check| Rx::Concurrent::Future.execute { check.check } }
91
+ .map(&:value)
92
+ .map { |r| { name: r.name, status: r.ok? ? 200 : 503, message: r.ok? ? "ok" : r.error, response_time_ms: r.timing } }
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,104 @@
1
+ # heap = []
2
+ # def add(value, heap)
3
+ # heap << value
4
+ # sort(heap)
5
+ # end
6
+ # def sort(heap)
7
+ # return if heap.length == 1
8
+ # last_parent = (heap.length - 2) / 2
9
+ # while last_parent >= 0
10
+ # l = last_parent * 2 + 1
11
+ # r = last_parent * 2 + 2
12
+ # s = last_parent
13
+
14
+ # if heap[l] < heap[last_parent]
15
+ # s = l
16
+ # end
17
+
18
+ # if r < heap.length && heap[r] < heap[last_parent]
19
+ # s = r
20
+ # end
21
+
22
+ # if s != last_parent
23
+ # heap[s], heap[last_parent] = heap[last_parent], heap[s]
24
+ # end
25
+
26
+ # last_parent -= 1
27
+ # end
28
+ # end
29
+
30
+ module Rx
31
+ module Util
32
+ class Heap
33
+ %i[empty? length size].each do |m|
34
+ define_method(m) { heap.send(m) }
35
+ end
36
+
37
+ def initialize(items = [], &comparator)
38
+ @heap = items.dup
39
+ @comparator = block_given? ? comparator : -> (a, b) { a < b }
40
+ sort!
41
+ end
42
+
43
+ def <<(item)
44
+ push(item)
45
+ end
46
+
47
+ def peek
48
+ heap.first
49
+ end
50
+
51
+ def pop
52
+ item = heap.shift
53
+ sort!
54
+ item
55
+ end
56
+
57
+ def push(item)
58
+ heap << item
59
+ sort!
60
+ self
61
+ end
62
+
63
+ private
64
+
65
+ attr_reader :comparator, :heap
66
+
67
+ def left(n)
68
+ 2 * n + 1
69
+ end
70
+
71
+ def parent(n)
72
+ (n - 1) / 2
73
+ end
74
+
75
+ def right(n)
76
+ 2 * n + 2
77
+ end
78
+
79
+ def sort!
80
+ return if heap.length <= 1
81
+ n = parent(heap.length - 1)
82
+ while n >= 0
83
+ l = left(n)
84
+ r = right(n)
85
+ s = n
86
+
87
+ if comparator.call(heap[l], heap[s])
88
+ s = l
89
+ end
90
+
91
+ if r < heap.length && comparator.call(heap[r], heap[s])
92
+ s = r
93
+ end
94
+
95
+ if s != n
96
+ heap[s], heap[n] = heap[n], heap[s]
97
+ end
98
+
99
+ n -= 1
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
data/lib/rx/version.rb ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rx
4
+ VERSION = "0.1.0"
5
+ end
data/rx.gemspec ADDED
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/rx/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "rx-healthcheck"
7
+ spec.version = Rx::VERSION
8
+ spec.authors = ["Zach Pendleton"]
9
+ spec.email = ["zachpendleton@gmail.com"]
10
+
11
+ spec.summary = "Standard health checks for Rails and Rack applications"
12
+ spec.homepage = "https://github.com/zachpendleton/rx"
13
+ spec.license = "MIT"
14
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.4.0")
15
+
16
+ spec.metadata["homepage_uri"] = spec.homepage
17
+ spec.metadata["source_code_uri"] = "https://github.com/zachpendleton/rx"
18
+
19
+ # Specify which files should be added to the gem when it is released.
20
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
21
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
22
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
23
+ end
24
+ spec.bindir = "exe"
25
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
26
+ spec.require_paths = ["lib"]
27
+
28
+ spec.add_dependency "simplecov", "0.21.2"
29
+
30
+ # For more information and examples about making a new gem, checkout our
31
+ # guide at: https://bundler.io/guides/creating_gem.html
32
+ end
metadata ADDED
@@ -0,0 +1,81 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rx-healthcheck
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Zach Pendleton
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2021-05-25 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: simplecov
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 0.21.2
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 0.21.2
27
+ description:
28
+ email:
29
+ - zachpendleton@gmail.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - ".gitignore"
35
+ - Gemfile
36
+ - Gemfile.lock
37
+ - LICENSE.txt
38
+ - README.md
39
+ - Rakefile
40
+ - bin/console
41
+ - bin/setup
42
+ - lib/rx.rb
43
+ - lib/rx/cache/in_memory_cache.rb
44
+ - lib/rx/cache/no_op_cache.rb
45
+ - lib/rx/check/active_record_check.rb
46
+ - lib/rx/check/file_system_check.rb
47
+ - lib/rx/check/generic_check.rb
48
+ - lib/rx/check/http_check.rb
49
+ - lib/rx/check/result.rb
50
+ - lib/rx/concurrent/future.rb
51
+ - lib/rx/concurrent/thread_pool.rb
52
+ - lib/rx/middleware.rb
53
+ - lib/rx/util/heap.rb
54
+ - lib/rx/version.rb
55
+ - rx.gemspec
56
+ homepage: https://github.com/zachpendleton/rx
57
+ licenses:
58
+ - MIT
59
+ metadata:
60
+ homepage_uri: https://github.com/zachpendleton/rx
61
+ source_code_uri: https://github.com/zachpendleton/rx
62
+ post_install_message:
63
+ rdoc_options: []
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: 2.4.0
71
+ required_rubygems_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ requirements: []
77
+ rubygems_version: 3.1.2
78
+ signing_key:
79
+ specification_version: 4
80
+ summary: Standard health checks for Rails and Rack applications
81
+ test_files: []