rx-healthcheck 0.1.6 → 0.1.9
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 +4 -4
- data/Gemfile.lock +3 -2
- data/README.md +40 -2
- data/lib/rx/cache/{in_memory_cache.rb → lru_cache.rb} +1 -1
- data/lib/rx/cache/map_cache.rb +45 -0
- data/lib/rx/concurrent/future.rb +5 -1
- data/lib/rx/middleware.rb +29 -11
- data/lib/rx/util/health_check_authorization.rb +25 -0
- data/lib/rx/version.rb +1 -1
- data/lib/rx.rb +3 -1
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ebf9af8d3b43d1640503ddcba7138d1ef6c04f298faa09b39c8d93fcb0d4eb50
|
4
|
+
data.tar.gz: e22f89c795207f5a3a78bb6f63c362624e6b4104e3834f6ca928ecb1c6fd5b79
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a194f56c544904474062a866aa7c91cfe6de9548b97802beaa448b4b082dab4c1fc3ffa7f41e3c0aa14b8f94c11d518e586d6984f1a82cbfaf0d2479abc9ce06
|
7
|
+
data.tar.gz: 1fc1ea21c9586cb3583d25ab7c8ab7177d0789ec085cc4de316dd136ebeb3c03872f30c2b54293c2efd254ea5ebae6d0255d86816488020a584e7c1b8c8b39f9
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
rx-healthcheck (0.1.
|
4
|
+
rx-healthcheck (0.1.8)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
@@ -17,6 +17,7 @@ GEM
|
|
17
17
|
simplecov_json_formatter (0.1.3)
|
18
18
|
|
19
19
|
PLATFORMS
|
20
|
+
ruby
|
20
21
|
x86_64-linux
|
21
22
|
|
22
23
|
DEPENDENCIES
|
@@ -26,4 +27,4 @@ DEPENDENCIES
|
|
26
27
|
simplecov (= 0.21.2)
|
27
28
|
|
28
29
|
BUNDLED WITH
|
29
|
-
2.2.
|
30
|
+
2.2.29
|
data/README.md
CHANGED
@@ -59,14 +59,52 @@ deep_secondary: []
|
|
59
59
|
|
60
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
61
|
|
62
|
+
### Cache
|
63
|
+
|
64
|
+
For deep health checks Rx by default will use an in-memory cache. While this is useful when running in production, during testing it could lead to unexpected results.
|
65
|
+
You can disable the in-memory cache by setting the cache key false in the options hash.
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
Rails.application.config.middleware.insert(
|
69
|
+
Rx::Middleware,
|
70
|
+
liveness: [Rx::Check::FileSystemCheck.new],
|
71
|
+
readiness: [
|
72
|
+
Rx::Check::FileSystemCheck.new,
|
73
|
+
Rx::Check::ActiveRecordCheck.new,
|
74
|
+
Rx::Check::HttpCheck.new("http://example.com"),
|
75
|
+
Rx::Check::GenericCheck.new(-> { $redis.ping == "PONG" }, "redis")],
|
76
|
+
deep_critical: [Rx::Check::HttpCheck.new("http://criticalservice.com/health")],
|
77
|
+
deep_secondary: [Rx::Check::HttpCheck.new("http://otherservice.com/health-check")],
|
78
|
+
options: {
|
79
|
+
cache: false
|
80
|
+
}
|
81
|
+
)
|
82
|
+
```
|
83
|
+
|
84
|
+
### Deep end-point authorization
|
85
|
+
|
86
|
+
It is considered as a good practice to protect the deep checks with a GUID to mitigate DDOS attacks. Hence you have 2 options to enable this. One is to use the `default_authorization` by passing the token to the authorization inside options hash, which you can use in a request with the authorization_token in the header of it. The other option would be to pass a lambda with an env argument (this gives you access to hash of request data) and have your own `custom_authorization`:
|
87
|
+
|
88
|
+
```ruby
|
89
|
+
options: {
|
90
|
+
#default
|
91
|
+
authorization: <token>
|
92
|
+
|
93
|
+
#custom
|
94
|
+
authorization: -> (env) {
|
95
|
+
#your code goes here
|
96
|
+
}
|
97
|
+
}
|
98
|
+
```
|
99
|
+
|
62
100
|
## Contributing
|
63
101
|
|
64
102
|
Bug reports and pull requests are welcome on GitHub at https://github.com/zachpendleton/rx.
|
65
103
|
|
66
104
|
Some tips for developing the gem locally:
|
67
105
|
|
68
|
-
|
69
|
-
|
106
|
+
- Tests can be run by calling `rake`
|
107
|
+
- 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
108
|
|
71
109
|
## License
|
72
110
|
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require "thread"
|
2
|
+
|
3
|
+
module Rx
|
4
|
+
module Cache
|
5
|
+
class MapCache
|
6
|
+
def initialize
|
7
|
+
@data = {}
|
8
|
+
@lock = Mutex.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def cache(k, expires_in = 60)
|
12
|
+
unless (value = get(k)).nil?
|
13
|
+
return value
|
14
|
+
end
|
15
|
+
|
16
|
+
value = yield
|
17
|
+
put(k, value, expires_in)
|
18
|
+
value
|
19
|
+
end
|
20
|
+
|
21
|
+
def get(k)
|
22
|
+
lock.synchronize do
|
23
|
+
value = data[k]
|
24
|
+
return nil unless value
|
25
|
+
|
26
|
+
if value[1] < Time.now
|
27
|
+
data.delete(k)
|
28
|
+
return nil
|
29
|
+
end
|
30
|
+
|
31
|
+
value[0]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def put(k, v, expires_in = 60)
|
36
|
+
lock.synchronize do
|
37
|
+
data[k] = [v, Time.now + expires_in]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
attr_reader :data, :lock
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/rx/concurrent/future.rb
CHANGED
@@ -32,7 +32,7 @@ module Rx
|
|
32
32
|
@state = :in_progress
|
33
33
|
pool.submit do
|
34
34
|
begin
|
35
|
-
channel << work
|
35
|
+
channel << execute_work(&work)
|
36
36
|
@state = :completed
|
37
37
|
rescue StandardError => ex
|
38
38
|
@error = ex
|
@@ -70,6 +70,10 @@ module Rx
|
|
70
70
|
def pool
|
71
71
|
@@pool
|
72
72
|
end
|
73
|
+
|
74
|
+
def execute_work(&block)
|
75
|
+
defined?(Rails) ? Rails.application.executor.wrap(&block) : block.call
|
76
|
+
end
|
73
77
|
end
|
74
78
|
end
|
75
79
|
end
|
data/lib/rx/middleware.rb
CHANGED
@@ -3,7 +3,8 @@ require "json"
|
|
3
3
|
module Rx
|
4
4
|
class Middleware
|
5
5
|
DEFAULT_OPTIONS = {
|
6
|
-
cache: true
|
6
|
+
cache: true,
|
7
|
+
authorization: nil
|
7
8
|
}.freeze
|
8
9
|
|
9
10
|
def initialize(app,
|
@@ -34,12 +35,16 @@ module Rx
|
|
34
35
|
when "/readiness"
|
35
36
|
readiness_response(check_to_component(readiness_checks))
|
36
37
|
when "/deep"
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
38
|
+
if !Rx::Util::HealthCheckAuthorization.new(env, @options[:authorization]).ok?
|
39
|
+
deep_response_authorization_failed
|
40
|
+
else
|
41
|
+
@cache.cache("deep") do
|
42
|
+
readiness = check_to_component(readiness_checks)
|
43
|
+
critical = check_to_component(deep_critical_checks)
|
44
|
+
secondary = check_to_component(deep_secondary_checks)
|
45
|
+
|
46
|
+
deep_response(readiness, critical, secondary)
|
47
|
+
end
|
43
48
|
end
|
44
49
|
end
|
45
50
|
end
|
@@ -50,11 +55,16 @@ module Rx
|
|
50
55
|
:deep_secondary_checks, :options
|
51
56
|
|
52
57
|
def cache_factory(options)
|
53
|
-
|
54
|
-
|
58
|
+
case options[:cache]
|
59
|
+
when true
|
60
|
+
Rx::Cache::LRUCache.new
|
61
|
+
when "LRU"
|
62
|
+
Rx::Cache::LRUCache.new
|
63
|
+
when "MAP"
|
64
|
+
Rx::Cache::MapCache.new
|
65
|
+
else
|
66
|
+
Rx::Cache::NoOpCache.new
|
55
67
|
end
|
56
|
-
|
57
|
-
Rx::Cache::InMemoryCache.new
|
58
68
|
end
|
59
69
|
|
60
70
|
def health_check_request?(path)
|
@@ -79,6 +89,14 @@ module Rx
|
|
79
89
|
]
|
80
90
|
end
|
81
91
|
|
92
|
+
def deep_response_authorization_failed
|
93
|
+
[
|
94
|
+
403,
|
95
|
+
{"content-type" => "application/json"},
|
96
|
+
[JSON.dump({ message: "authorization failed" })]
|
97
|
+
]
|
98
|
+
end
|
99
|
+
|
82
100
|
def deep_response(readiness, critical, secondary)
|
83
101
|
status = (readiness.map { |x| x[:status] == 200 } + critical.map { |x| x[:status] == 200 }).all? ? 200 : 503
|
84
102
|
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Rx
|
2
|
+
module Util
|
3
|
+
class HealthCheckAuthorization
|
4
|
+
HTTP_HEADER = "HTTP_AUTHORIZATION"
|
5
|
+
|
6
|
+
def initialize(env, authorization)
|
7
|
+
@authorization = authorization
|
8
|
+
@env = env
|
9
|
+
end
|
10
|
+
|
11
|
+
def ok?
|
12
|
+
case @authorization
|
13
|
+
when NilClass
|
14
|
+
true
|
15
|
+
when Proc
|
16
|
+
@authorization.call(@env)
|
17
|
+
when String
|
18
|
+
@authorization == @env[HTTP_HEADER]
|
19
|
+
else
|
20
|
+
raise StandardError.new("Authorization is not configured properly")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/rx/version.rb
CHANGED
data/lib/rx.rb
CHANGED
@@ -2,7 +2,8 @@
|
|
2
2
|
|
3
3
|
require_relative "rx/version"
|
4
4
|
require_relative "rx/middleware"
|
5
|
-
require_relative "rx/cache/
|
5
|
+
require_relative "rx/cache/lru_cache"
|
6
|
+
require_relative "rx/cache/map_cache"
|
6
7
|
require_relative "rx/cache/no_op_cache"
|
7
8
|
require_relative "rx/check/active_record_check"
|
8
9
|
require_relative "rx/check/file_system_check"
|
@@ -12,6 +13,7 @@ require_relative "rx/check/result"
|
|
12
13
|
require_relative "rx/concurrent/future"
|
13
14
|
require_relative "rx/concurrent/thread_pool"
|
14
15
|
require_relative "rx/util/heap"
|
16
|
+
require_relative "rx/util/health_check_authorization"
|
15
17
|
|
16
18
|
module Rx
|
17
19
|
class Error < StandardError; end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rx-healthcheck
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Zach Pendleton
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-04-27 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email:
|
@@ -26,7 +26,8 @@ files:
|
|
26
26
|
- bin/console
|
27
27
|
- bin/setup
|
28
28
|
- lib/rx.rb
|
29
|
-
- lib/rx/cache/
|
29
|
+
- lib/rx/cache/lru_cache.rb
|
30
|
+
- lib/rx/cache/map_cache.rb
|
30
31
|
- lib/rx/cache/no_op_cache.rb
|
31
32
|
- lib/rx/check/active_record_check.rb
|
32
33
|
- lib/rx/check/file_system_check.rb
|
@@ -36,6 +37,7 @@ files:
|
|
36
37
|
- lib/rx/concurrent/future.rb
|
37
38
|
- lib/rx/concurrent/thread_pool.rb
|
38
39
|
- lib/rx/middleware.rb
|
40
|
+
- lib/rx/util/health_check_authorization.rb
|
39
41
|
- lib/rx/util/heap.rb
|
40
42
|
- lib/rx/version.rb
|
41
43
|
- rx.gemspec
|