network_resiliency 0.6.8 → 0.7.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b907866b5327e9488dca8b828bbf3b14c84a257c6a62c6381197455f11fc337b
4
- data.tar.gz: 8aa6d3fbe7a1a0bae41711b18f02659363b620af749bc9cc778fd244398c9e36
3
+ metadata.gz: 0b05ddc43d74cc05325b32b3a45cbc1377bee1228c2c2f8ad7f2fd717ed7b49f
4
+ data.tar.gz: 8a9b5274e52a3ebc039f00e4aad18af9a7c2e645a7a246fd9e45cc474bbfb50b
5
5
  SHA512:
6
- metadata.gz: 98c21b67a95c4ac785df751ae874e53f5116908462e5d17944831202e414ddc3644601d7e9c3ca6b00703a900490e56d575cff7a896a2606ef3167521ebfde88
7
- data.tar.gz: 7f9d19f1546bfb251243cd142899af1eb74d561e9004e25b91b28e072d7f23f68646c0c2ba5b145ab933c28eafc762303e56811169ce4dd8f2822f60a235bef5
6
+ metadata.gz: ffe3b488a66c2721a25a3a995a007ff89a822d4ea2b85638b370535a4895968c5e74084ef89ee7a9bc97a325beba410f74e4ce2ecf4c941e99b00bc3f07daf4a
7
+ data.tar.gz: 5632e5111b856b1fc9d34b31f8d099b584491dbb9beb623ddcff016a058b8f839900fe65554ef60619930843b5b98c4137b92f15722c5040547632b91ec5ac7e
data/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ### v0.7.0 (2023-12-11)
2
+ - proc support for mode
3
+ - rails adapater and deadline
4
+
5
+ ### v0.6.9 (2023-12-07)
6
+ - tag mode
7
+ - request timeout header
8
+
1
9
  ### v0.6.8 (2023-12-04)
2
10
  - slim metrics
3
11
 
data/Gemfile.lock CHANGED
@@ -1,14 +1,95 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- network_resiliency (0.6.8)
4
+ network_resiliency (0.7.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
+ actioncable (7.1.2)
10
+ actionpack (= 7.1.2)
11
+ activesupport (= 7.1.2)
12
+ nio4r (~> 2.0)
13
+ websocket-driver (>= 0.6.1)
14
+ zeitwerk (~> 2.6)
15
+ actionmailbox (7.1.2)
16
+ actionpack (= 7.1.2)
17
+ activejob (= 7.1.2)
18
+ activerecord (= 7.1.2)
19
+ activestorage (= 7.1.2)
20
+ activesupport (= 7.1.2)
21
+ mail (>= 2.7.1)
22
+ net-imap
23
+ net-pop
24
+ net-smtp
25
+ actionmailer (7.1.2)
26
+ actionpack (= 7.1.2)
27
+ actionview (= 7.1.2)
28
+ activejob (= 7.1.2)
29
+ activesupport (= 7.1.2)
30
+ mail (~> 2.5, >= 2.5.4)
31
+ net-imap
32
+ net-pop
33
+ net-smtp
34
+ rails-dom-testing (~> 2.2)
35
+ actionpack (7.1.2)
36
+ actionview (= 7.1.2)
37
+ activesupport (= 7.1.2)
38
+ nokogiri (>= 1.8.5)
39
+ racc
40
+ rack (>= 2.2.4)
41
+ rack-session (>= 1.0.1)
42
+ rack-test (>= 0.6.3)
43
+ rails-dom-testing (~> 2.2)
44
+ rails-html-sanitizer (~> 1.6)
45
+ actiontext (7.1.2)
46
+ actionpack (= 7.1.2)
47
+ activerecord (= 7.1.2)
48
+ activestorage (= 7.1.2)
49
+ activesupport (= 7.1.2)
50
+ globalid (>= 0.6.0)
51
+ nokogiri (>= 1.8.5)
52
+ actionview (7.1.2)
53
+ activesupport (= 7.1.2)
54
+ builder (~> 3.1)
55
+ erubi (~> 1.11)
56
+ rails-dom-testing (~> 2.2)
57
+ rails-html-sanitizer (~> 1.6)
58
+ activejob (7.1.2)
59
+ activesupport (= 7.1.2)
60
+ globalid (>= 0.3.6)
61
+ activemodel (7.1.2)
62
+ activesupport (= 7.1.2)
63
+ activerecord (7.1.2)
64
+ activemodel (= 7.1.2)
65
+ activesupport (= 7.1.2)
66
+ timeout (>= 0.4.0)
67
+ activestorage (7.1.2)
68
+ actionpack (= 7.1.2)
69
+ activejob (= 7.1.2)
70
+ activerecord (= 7.1.2)
71
+ activesupport (= 7.1.2)
72
+ marcel (~> 1.0)
73
+ activesupport (7.1.2)
74
+ base64
75
+ bigdecimal
76
+ concurrent-ruby (~> 1.0, >= 1.0.2)
77
+ connection_pool (>= 2.2.5)
78
+ drb
79
+ i18n (>= 1.6, < 2)
80
+ minitest (>= 5.1)
81
+ mutex_m
82
+ tzinfo (~> 2.0)
83
+ base64 (0.2.0)
84
+ bigdecimal (3.1.4)
85
+ builder (3.2.4)
9
86
  byebug (11.1.3)
87
+ concurrent-ruby (1.2.2)
88
+ connection_pool (2.4.1)
89
+ crass (1.0.6)
10
90
  datadog-ci (0.2.0)
11
91
  msgpack
92
+ date (3.3.4)
12
93
  ddtrace (1.15.0)
13
94
  datadog-ci (~> 0.2.0)
14
95
  debase-ruby_core_source (= 3.2.2)
@@ -19,6 +100,9 @@ GEM
19
100
  diff-lcs (1.5.0)
20
101
  docile (1.4.0)
21
102
  dogstatsd-ruby (4.8.3)
103
+ drb (2.2.0)
104
+ ruby2_keywords
105
+ erubi (1.12.0)
22
106
  faraday (1.10.3)
23
107
  faraday-em_http (~> 1.0)
24
108
  faraday-em_synchrony (~> 1.0)
@@ -43,17 +127,93 @@ GEM
43
127
  faraday-rack (1.0.0)
44
128
  faraday-retry (1.0.3)
45
129
  ffi (1.16.3)
130
+ globalid (1.2.1)
131
+ activesupport (>= 6.1)
132
+ i18n (1.14.1)
133
+ concurrent-ruby (~> 1.0)
134
+ io-console (0.6.0)
135
+ irb (1.10.1)
136
+ rdoc
137
+ reline (>= 0.3.8)
46
138
  libdatadog (5.0.0.1.0)
47
139
  libddwaf (1.14.0.0.0)
48
140
  ffi (~> 1.0)
141
+ loofah (2.22.0)
142
+ crass (~> 1.0.2)
143
+ nokogiri (>= 1.12.0)
144
+ mail (2.8.1)
145
+ mini_mime (>= 0.1.1)
146
+ net-imap
147
+ net-pop
148
+ net-smtp
149
+ marcel (1.0.2)
150
+ mini_mime (1.1.5)
151
+ mini_portile2 (2.8.5)
152
+ minitest (5.20.0)
49
153
  msgpack (1.7.2)
50
154
  multipart-post (2.3.0)
155
+ mutex_m (0.2.0)
51
156
  mysql2 (0.5.5)
157
+ net-imap (0.4.7)
158
+ date
159
+ net-protocol
160
+ net-pop (0.1.2)
161
+ net-protocol
162
+ net-protocol (0.2.2)
163
+ timeout
164
+ net-smtp (0.4.0)
165
+ net-protocol
166
+ nio4r (2.7.0)
167
+ nokogiri (1.15.5)
168
+ mini_portile2 (~> 2.8.2)
169
+ racc (~> 1.4)
52
170
  pg (1.5.4)
171
+ psych (5.1.1.1)
172
+ stringio
173
+ racc (1.7.3)
53
174
  rack (3.0.8)
175
+ rack-session (2.0.0)
176
+ rack (>= 3.0.0)
54
177
  rack-test (2.1.0)
55
178
  rack (>= 1.3)
179
+ rackup (2.1.0)
180
+ rack (>= 3)
181
+ webrick (~> 1.8)
182
+ rails (7.1.2)
183
+ actioncable (= 7.1.2)
184
+ actionmailbox (= 7.1.2)
185
+ actionmailer (= 7.1.2)
186
+ actionpack (= 7.1.2)
187
+ actiontext (= 7.1.2)
188
+ actionview (= 7.1.2)
189
+ activejob (= 7.1.2)
190
+ activemodel (= 7.1.2)
191
+ activerecord (= 7.1.2)
192
+ activestorage (= 7.1.2)
193
+ activesupport (= 7.1.2)
194
+ bundler (>= 1.15.0)
195
+ railties (= 7.1.2)
196
+ rails-dom-testing (2.2.0)
197
+ activesupport (>= 5.0.0)
198
+ minitest
199
+ nokogiri (>= 1.6)
200
+ rails-html-sanitizer (1.6.0)
201
+ loofah (~> 2.21)
202
+ nokogiri (~> 1.14)
203
+ railties (7.1.2)
204
+ actionpack (= 7.1.2)
205
+ activesupport (= 7.1.2)
206
+ irb
207
+ rackup (>= 1.0.0)
208
+ rake (>= 12.2)
209
+ thor (~> 1.0, >= 1.2.2)
210
+ zeitwerk (~> 2.6)
211
+ rake (13.1.0)
212
+ rdoc (6.6.1)
213
+ psych (>= 4.0.0)
56
214
  redis (4.8.1)
215
+ reline (0.4.1)
216
+ io-console (~> 0.5)
57
217
  rspec (3.12.0)
58
218
  rspec-core (~> 3.12.0)
59
219
  rspec-expectations (~> 3.12.0)
@@ -66,6 +226,14 @@ GEM
66
226
  rspec-mocks (3.12.6)
67
227
  diff-lcs (>= 1.2.0, < 2.0)
68
228
  rspec-support (~> 3.12.0)
229
+ rspec-rails (6.1.0)
230
+ actionpack (>= 6.1)
231
+ activesupport (>= 6.1)
232
+ railties (>= 6.1)
233
+ rspec-core (~> 3.12)
234
+ rspec-expectations (~> 3.12)
235
+ rspec-mocks (~> 3.12)
236
+ rspec-support (~> 3.12)
69
237
  rspec-support (3.12.1)
70
238
  ruby2_keywords (0.0.5)
71
239
  simplecov (0.22.0)
@@ -74,6 +242,17 @@ GEM
74
242
  simplecov_json_formatter (~> 0.1)
75
243
  simplecov-html (0.12.3)
76
244
  simplecov_json_formatter (0.1.4)
245
+ stringio (3.1.0)
246
+ thor (1.3.0)
247
+ timecop (0.9.8)
248
+ timeout (0.4.1)
249
+ tzinfo (2.0.6)
250
+ concurrent-ruby (~> 1.0)
251
+ webrick (1.8.1)
252
+ websocket-driver (0.7.6)
253
+ websocket-extensions (>= 0.1.0)
254
+ websocket-extensions (0.1.5)
255
+ zeitwerk (2.6.12)
77
256
 
78
257
  PLATFORMS
79
258
  ruby
@@ -89,9 +268,12 @@ DEPENDENCIES
89
268
  pg (~> 1.1)
90
269
  rack
91
270
  rack-test
271
+ rails (>= 5)
92
272
  redis (~> 4)
93
273
  rspec
274
+ rspec-rails
94
275
  simplecov
276
+ timecop
95
277
 
96
278
  BUNDLED WITH
97
279
  2.4.20
data/README.md CHANGED
@@ -13,9 +13,6 @@ require "network_resiliency"
13
13
 
14
14
  NetworkResiliency.configure do |conf|
15
15
  conf.statsd = Datadog::Statsd.new
16
-
17
- # patch Redis instances
18
- conf.patch :redis
19
16
  end
20
17
 
21
18
  Redis.new.ping
@@ -5,6 +5,15 @@ module NetworkResiliency
5
5
  module HTTP
6
6
  extend self
7
7
 
8
+ ERRORS = [
9
+ Timeout::Error,
10
+ IOError,
11
+ SystemCallError,
12
+ (OpenSSL::OpenSSLError if defined?(OpenSSL::SSL)),
13
+ ].compact
14
+
15
+ REQUEST_TIMEOUT_HEADER = "X-Request-Timeout"
16
+
8
17
  def patch(instance = nil)
9
18
  return if patched?(instance)
10
19
 
@@ -39,8 +48,8 @@ module NetworkResiliency
39
48
  end
40
49
 
41
50
  timeouts = NetworkResiliency.timeouts_for(
42
- adapter: "http",
43
- action: action.to_s,
51
+ adapter: :http,
52
+ action: action,
44
53
  destination: destination,
45
54
  max: original_timeout,
46
55
  units: :seconds,
@@ -61,13 +70,11 @@ module NetworkResiliency
61
70
  attempts += 1
62
71
  error = nil
63
72
 
64
- set_timeout.call(timeouts.shift)
65
-
66
- yield
67
- rescue ::Timeout::Error,
68
- defined?(OpenSSL::SSL) ? OpenSSL::OpenSSLError : IOError,
69
- SystemCallError => e
73
+ timeout = timeouts.shift
74
+ set_timeout.call(timeout)
70
75
 
76
+ yield timeout
77
+ rescue *ERRORS => e
71
78
  # capture error
72
79
  error = e.class
73
80
 
@@ -80,8 +87,8 @@ module NetworkResiliency
80
87
  self.max_retries = original_max_retries
81
88
 
82
89
  NetworkResiliency.record(
83
- adapter: "http",
84
- action: action.to_s,
90
+ adapter: :http,
91
+ action: action,
85
92
  destination: destination,
86
93
  duration: ts,
87
94
  error: error,
@@ -115,7 +122,12 @@ module NetworkResiliency
115
122
 
116
123
  idepotent = Net::HTTP::IDEMPOTENT_METHODS_.include?(req.method)
117
124
 
118
- with_resilience(:request, destination, idepotent) { super }
125
+ with_resilience(:request, destination, idepotent) do |timeout|
126
+ # send timeout via headers
127
+ req[REQUEST_TIMEOUT_HEADER] = timeout
128
+
129
+ super
130
+ end
119
131
  end
120
132
  end
121
133
  end
@@ -31,8 +31,8 @@ module NetworkResiliency
31
31
  ts += NetworkResiliency.timestamp
32
32
 
33
33
  NetworkResiliency.record(
34
- adapter: "mysql",
35
- action: "connect",
34
+ adapter: :mysql,
35
+ action: :connect,
36
36
  destination: host,
37
37
  error: e&.class,
38
38
  duration: ts,
@@ -33,8 +33,8 @@ module NetworkResiliency
33
33
  ts += NetworkResiliency.timestamp
34
34
 
35
35
  NetworkResiliency.record(
36
- adapter: "postgres",
37
- action: "connect",
36
+ adapter: :postgres,
37
+ action: :connect,
38
38
  destination: host,
39
39
  error: e&.class,
40
40
  duration: ts,
@@ -0,0 +1,48 @@
1
+ gem "rails", ">= 5"
2
+ require "rails"
3
+
4
+ module NetworkResiliency
5
+ module Adapter
6
+ module Rails
7
+ extend self
8
+
9
+ def patch(instance = nil)
10
+ instance ||= ::Rails.application
11
+
12
+ unless instance.is_a?(::Rails::Application)
13
+ raise ArgumentError, "expected Rails::Application instance, found: #{instance}"
14
+ end
15
+
16
+ return if patched?(instance)
17
+
18
+ instance.config.middleware.use Middleware
19
+ end
20
+
21
+ def patched?(instance = nil)
22
+ instance ||= ::Rails.application
23
+
24
+ return false unless instance.initialized?
25
+
26
+ instance.config.middleware.include?(Middleware)
27
+ end
28
+
29
+ class Middleware
30
+ def initialize(app)
31
+ @app = app
32
+ end
33
+
34
+ def call(env)
35
+ header = HTTP::REQUEST_TIMEOUT_HEADER.upcase.tr('-', '_')
36
+ timeout = env["HTTP_#{header}"]&.to_f
37
+
38
+ NetworkResiliency.deadline = timeout if timeout
39
+
40
+ @app.call(env)
41
+ ensure
42
+ NetworkResiliency.deadline = nil
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+
@@ -61,8 +61,8 @@ module NetworkResiliency
61
61
  original_timeout = @options[timeout_key]
62
62
 
63
63
  timeouts = NetworkResiliency.timeouts_for(
64
- adapter: "redis",
65
- action: action.to_s,
64
+ adapter: :redis,
65
+ action: action,
66
66
  destination: destination,
67
67
  max: @options[timeout_key],
68
68
  units: :seconds,
@@ -101,8 +101,8 @@ module NetworkResiliency
101
101
  @options[timeout_key] = original_timeout
102
102
 
103
103
  NetworkResiliency.record(
104
- adapter: "redis",
105
- action: action.to_s,
104
+ adapter: :redis,
105
+ action: action,
106
106
  destination: destination,
107
107
  duration: ts,
108
108
  error: error,
@@ -1,3 +1,3 @@
1
1
  module NetworkResiliency
2
- VERSION = "0.6.8"
2
+ VERSION = "0.7.0"
3
3
  end
@@ -13,10 +13,11 @@ module NetworkResiliency
13
13
  autoload :Redis, "network_resiliency/adapter/redis"
14
14
  autoload :Mysql, "network_resiliency/adapter/mysql"
15
15
  autoload :Postgres, "network_resiliency/adapter/postgres"
16
+ autoload :Rails, "network_resiliency/adapter/rails"
16
17
  end
17
18
 
18
19
  ACTIONS = [ :connect, :request ].freeze
19
- ADAPTERS = [ :http, :faraday, :redis, :mysql, :postgres ].freeze
20
+ ADAPTERS = [ :http, :faraday, :redis, :mysql, :postgres, :rails ].freeze
20
21
  MODE = [ :observe, :resilient ].freeze
21
22
  RESILIENCY_SIZE_THRESHOLD = 1_000
22
23
 
@@ -49,6 +50,8 @@ module NetworkResiliency
49
50
  Adapter::Mysql.patch
50
51
  when :postgres
51
52
  Adapter::Postgres.patch
53
+ when :rails
54
+ Adapter::Rails.patch
52
55
  else
53
56
  raise NotImplementedError
54
57
  end
@@ -108,13 +111,38 @@ module NetworkResiliency
108
111
  raise ArgumentError, "invalid NetworkResiliency action: #{action}"
109
112
  end
110
113
 
111
- (@mode && @mode[action]) || :observe
114
+ mode = if @mode.is_a?(Proc)
115
+ @mode.call(action)
116
+ elsif @mode
117
+ @mode[action]
118
+ end || :observe
119
+
120
+ unless MODE.include?(mode)
121
+ raise ArgumentError, "invalid NetworkResiliency mode: #{mode}"
122
+ end
123
+
124
+ mode
125
+ rescue => e
126
+ NetworkResiliency.statsd&.increment(
127
+ "network_resiliency.error",
128
+ tags: {
129
+ method: __method__,
130
+ type: e.class,
131
+ },
132
+ )
133
+
134
+ warn "[ERROR] NetworkResiliency: #{e.class}: #{e.message}"
135
+
136
+ :observe
112
137
  end
113
138
 
114
139
  def mode=(mode)
115
140
  @mode = {}
116
141
 
117
- if mode.is_a?(Hash)
142
+ case mode
143
+ when Proc
144
+ @mode = mode
145
+ when Hash
118
146
  invalid = mode.keys - ACTIONS
119
147
 
120
148
  unless invalid.empty?
@@ -139,6 +167,25 @@ module NetworkResiliency
139
167
  @mode.freeze
140
168
  end
141
169
 
170
+ def deadline
171
+ thread_state["deadline"]
172
+ end
173
+
174
+ def deadline=(ts)
175
+ thread_state["deadline"] = case ts
176
+ when Numeric
177
+ Time.now + ts
178
+ when Time
179
+ ts
180
+ when nil
181
+ nil
182
+ else
183
+ raise ArgumentError, "invalid deadline: #{ts}"
184
+ end
185
+
186
+ # warn or raise if we're already past the deadline?
187
+ end
188
+
142
189
  def normalize_request(adapter, request = nil, **context, &block)
143
190
  unless ADAPTERS.include?(adapter)
144
191
  raise ArgumentError, "invalid adapter: #{adapter}"
@@ -177,6 +224,7 @@ module NetworkResiliency
177
224
  adapter: adapter,
178
225
  destination: destination,
179
226
  error: error,
227
+ mode: mode(action),
180
228
  attempts: (attempts if attempts > 1),
181
229
  }.compact,
182
230
  )
@@ -22,7 +22,10 @@ Gem::Specification.new do |s|
22
22
  s.add_development_dependency "pg", "~> 1.1"
23
23
  s.add_development_dependency "rack"
24
24
  s.add_development_dependency "rack-test"
25
+ s.add_development_dependency "rails", ">= 5"
25
26
  s.add_development_dependency "redis", "~> 4"
26
27
  s.add_development_dependency "rspec"
28
+ s.add_development_dependency "rspec-rails"
27
29
  s.add_development_dependency "simplecov"
30
+ s.add_development_dependency "timecop"
28
31
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: network_resiliency
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.8
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Pepper
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-12-04 00:00:00.000000000 Z
11
+ date: 2023-12-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: byebug
@@ -136,6 +136,20 @@ dependencies:
136
136
  - - ">="
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: rails
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '5'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '5'
139
153
  - !ruby/object:Gem::Dependency
140
154
  name: redis
141
155
  requirement: !ruby/object:Gem::Requirement
@@ -164,6 +178,20 @@ dependencies:
164
178
  - - ">="
165
179
  - !ruby/object:Gem::Version
166
180
  version: '0'
181
+ - !ruby/object:Gem::Dependency
182
+ name: rspec-rails
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ version: '0'
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - ">="
193
+ - !ruby/object:Gem::Version
194
+ version: '0'
167
195
  - !ruby/object:Gem::Dependency
168
196
  name: simplecov
169
197
  requirement: !ruby/object:Gem::Requirement
@@ -178,6 +206,20 @@ dependencies:
178
206
  - - ">="
179
207
  - !ruby/object:Gem::Version
180
208
  version: '0'
209
+ - !ruby/object:Gem::Dependency
210
+ name: timecop
211
+ requirement: !ruby/object:Gem::Requirement
212
+ requirements:
213
+ - - ">="
214
+ - !ruby/object:Gem::Version
215
+ version: '0'
216
+ type: :development
217
+ prerelease: false
218
+ version_requirements: !ruby/object:Gem::Requirement
219
+ requirements:
220
+ - - ">="
221
+ - !ruby/object:Gem::Version
222
+ version: '0'
181
223
  description: "..."
182
224
  email:
183
225
  executables: []
@@ -194,6 +236,7 @@ files:
194
236
  - lib/network_resiliency/adapter/http.rb
195
237
  - lib/network_resiliency/adapter/mysql.rb
196
238
  - lib/network_resiliency/adapter/postgres.rb
239
+ - lib/network_resiliency/adapter/rails.rb
197
240
  - lib/network_resiliency/adapter/redis.rb
198
241
  - lib/network_resiliency/refinements.rb
199
242
  - lib/network_resiliency/stats.rb