restify 1.13.0 → 1.15.2
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/CHANGELOG.md +98 -6
- data/lib/restify/adapter/em.rb +6 -13
- data/lib/restify/adapter/pooled_em.rb +35 -40
- data/lib/restify/adapter/typhoeus.rb +57 -51
- data/lib/restify/context.rb +5 -9
- data/lib/restify/error.rb +24 -0
- data/lib/restify/global.rb +1 -0
- data/lib/restify/logging.rb +1 -1
- data/lib/restify/processors/base/parsing.rb +5 -9
- data/lib/restify/processors/base.rb +2 -6
- data/lib/restify/promise.rb +1 -3
- data/lib/restify/request.rb +13 -5
- data/lib/restify/resource.rb +2 -2
- data/lib/restify/response.rb +0 -2
- data/lib/restify/timeout.rb +1 -3
- data/lib/restify/version.rb +3 -3
- data/spec/restify/cache_spec.rb +2 -2
- data/spec/restify/context_spec.rb +10 -7
- data/spec/restify/error_spec.rb +10 -0
- data/spec/restify/features/head_requests_spec.rb +7 -7
- data/spec/restify/features/request_bodies_spec.rb +84 -0
- data/spec/restify/features/request_errors_spec.rb +19 -0
- data/spec/restify/features/request_headers_spec.rb +16 -17
- data/spec/restify/features/response_errors_spec.rb +127 -0
- data/spec/restify/global_spec.rb +6 -6
- data/spec/restify/link_spec.rb +9 -9
- data/spec/restify/processors/base_spec.rb +1 -0
- data/spec/restify/processors/json_spec.rb +2 -1
- data/spec/restify/processors/msgpack_spec.rb +8 -7
- data/spec/restify/promise_spec.rb +8 -4
- data/spec/restify/registry_spec.rb +2 -2
- data/spec/restify/relation_spec.rb +18 -17
- data/spec/restify/resource_spec.rb +9 -8
- data/spec/restify/timeout_spec.rb +4 -4
- data/spec/restify_spec.rb +52 -57
- data/spec/spec_helper.rb +11 -8
- data/spec/support/stub_server.rb +106 -0
- metadata +30 -23
- data/spec/restify/features/response_errors.rb +0 -79
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c29c95a9b1c0b18f2a73b51c99da7cdddf163e1cee33c43272810f5557b1375b
|
4
|
+
data.tar.gz: 95f956684154058cc6f25b7d4ffebde6706864b00c1369e91c8f8b5fcc50f0d9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f420cc4d0c4ebbdade1bc1a780c24218b5eea707bd8e420c113d155d58067936464dc3d4807717de8f515ed586784c9f13476b46c66f68c8d1181501937db3a2
|
7
|
+
data.tar.gz: 71da11cdf50d25abc968af02c6157c63f1aa5703c88f7ae28c3394aa028d9f038013d220283510532f7b540dffc69d0abad5fe4952c4e27df4910a4009475ae5
|
data/CHANGELOG.md
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
# Changelog
|
2
|
+
|
2
3
|
All notable changes to this project will be documented in this file.
|
3
4
|
|
4
5
|
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
5
6
|
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
6
7
|
|
7
8
|
|
8
|
-
|
9
9
|
## Unreleased
|
10
10
|
---
|
11
11
|
|
@@ -18,135 +18,227 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|
18
18
|
### Breaks
|
19
19
|
|
20
20
|
|
21
|
+
## 1.15.2 - (2021-12-23)
|
22
|
+
|
23
|
+
---
|
24
|
+
|
25
|
+
### Fixes
|
26
|
+
|
27
|
+
- ActiveSupport v7.0 issues with cache module
|
28
|
+
|
29
|
+
|
30
|
+
## 1.15.1 - (2021-07-15)
|
31
|
+
|
32
|
+
---
|
33
|
+
|
34
|
+
### Fixes
|
35
|
+
|
36
|
+
- Typhoeus internal exception when request timed out
|
37
|
+
|
38
|
+
## 1.15.0 - (2021-07-09)
|
39
|
+
|
40
|
+
---
|
41
|
+
|
42
|
+
### New
|
43
|
+
|
44
|
+
- Improve memory usage when running lots of requests with typhoeus adapter
|
45
|
+
- Use hydra for synchronous requests
|
46
|
+
- Increased thread stability of typhoeus adapter (new internal queuing mechanism)
|
47
|
+
|
48
|
+
### Changes
|
49
|
+
|
50
|
+
- Use Ruby 2.5 as baseline for testing and linting
|
51
|
+
- Add Ruby 3.0 to automated testing
|
52
|
+
- Changed timing behavior for multiple requests due to new internal queuing mechanism for the typhoeus adapter
|
53
|
+
|
54
|
+
## 1.14.0 - (2020-12-15)
|
55
|
+
|
56
|
+
---
|
57
|
+
|
58
|
+
### New
|
59
|
+
|
60
|
+
- Allow making requests with non-JSON bodies and custom content types (#42)
|
61
|
+
|
21
62
|
## 1.13.0 - (2020-06-12)
|
63
|
+
|
22
64
|
---
|
23
65
|
|
24
66
|
### New
|
25
|
-
* typhoeus: Support setting per-request libcurl options on adapter
|
26
|
-
* typhoeus: Enable short TCP keepalive probes by default (5s/5s)
|
27
67
|
|
68
|
+
- typhoeus: Support setting per-request libcurl options on adapter
|
69
|
+
- typhoeus: Enable short TCP keepalive probes by default (5s/5s)
|
28
70
|
|
29
71
|
## 1.12.0 - (2020-04-01)
|
72
|
+
|
30
73
|
---
|
31
74
|
|
32
75
|
### Added
|
33
|
-
|
76
|
+
|
77
|
+
- Explicit exception class for HTTP status code 410 (Gone)
|
34
78
|
|
35
79
|
### Changed
|
36
80
|
|
37
81
|
### Fixed
|
38
|
-
* `GatewayError` exception classes introduced in v1.11.0 now properly inherit from `ServerError` (#30)
|
39
82
|
|
83
|
+
- `GatewayError` exception classes introduced in v1.11.0 now properly inherit from `ServerError` (#30)
|
40
84
|
|
41
85
|
## 1.11.0 - (2019-07-11)
|
86
|
+
|
42
87
|
### Added
|
43
|
-
|
88
|
+
|
89
|
+
- Explicit exception classes for HTTP status codes 500, 502, 503, 504
|
44
90
|
|
45
91
|
## 1.10.0 - 2018-12-11
|
92
|
+
|
46
93
|
### Changed
|
94
|
+
|
47
95
|
- Raise more specific error on a few status codes (#17)
|
48
96
|
- Complete promises with an empty list (but a list) of dependencies (#18)
|
49
97
|
|
50
98
|
## 1.9.0 - 2018-11-13
|
99
|
+
|
51
100
|
### Changed
|
101
|
+
|
52
102
|
- Do not raise error on 3XX responses but return responses
|
53
103
|
|
54
104
|
## 1.8.0 - 2018-08-22
|
105
|
+
|
55
106
|
### Added
|
107
|
+
|
56
108
|
- Add HEAD request method (#16)
|
57
109
|
|
58
110
|
## 1.7.0 - 2018-08-15
|
111
|
+
|
59
112
|
### Added
|
113
|
+
|
60
114
|
- Introduce promise dependency timeouts (#15)
|
61
115
|
|
62
116
|
## 1.6.0 - 2018-08-09
|
117
|
+
|
63
118
|
### Changed
|
119
|
+
|
64
120
|
- Specify headers on restify clients and individual requests (#14)
|
65
121
|
|
66
122
|
## 1.5.0 - 2018-07-31
|
123
|
+
|
67
124
|
### Added
|
125
|
+
|
68
126
|
- Add MessagePack processor enabled by default
|
69
127
|
|
70
128
|
### Changed
|
129
|
+
|
71
130
|
- Tune typhoeus adapter to be more race-condition resilent
|
72
131
|
|
73
132
|
## 1.4.4 - 2018-07-13
|
133
|
+
|
74
134
|
### Added
|
135
|
+
|
75
136
|
- Add `#request` to `NetworkError` to ease debugging
|
76
137
|
|
77
138
|
### Changed
|
139
|
+
|
78
140
|
- Fix race condition in typhoeus adapter
|
79
141
|
|
80
142
|
## 1.4.3 - 2017-11-15
|
143
|
+
|
81
144
|
### Added
|
145
|
+
|
82
146
|
- Add advanced logging capabilities using logging gem
|
83
147
|
|
84
148
|
### Changed
|
149
|
+
|
85
150
|
- Improve compatibility with webmocks returning `nil` as headers
|
86
151
|
|
87
152
|
## 1.4.1 - 2017-11-15
|
153
|
+
|
88
154
|
### Changed
|
155
|
+
|
89
156
|
- Fix possible deadlock issues
|
90
157
|
|
91
158
|
## 1.4.0 - 2017-11-10
|
159
|
+
|
92
160
|
### Added
|
161
|
+
|
93
162
|
- Add timeout option to requests (only supported by typhoeus adapter)
|
94
163
|
|
95
164
|
### Changed
|
165
|
+
|
96
166
|
- Fix possible concurrency issue with typhoeus adapter
|
97
167
|
|
98
168
|
## 1.3.1 - 2017-11-10
|
169
|
+
|
99
170
|
### Changed
|
171
|
+
|
100
172
|
- Improve typhoeus adapters initial request queuing
|
101
173
|
- Disable default pipelining
|
102
174
|
|
103
175
|
## 1.3.0 - 2017-11-08
|
176
|
+
|
104
177
|
### Changed
|
178
|
+
|
105
179
|
- Improve typhoeus adapter to better utilize concurrency
|
106
180
|
- Default to new typhoeus adapter
|
107
181
|
|
108
182
|
## 1.2.1 - 2017-10-30
|
183
|
+
|
109
184
|
### Changed
|
185
|
+
|
110
186
|
- Fix issue with Ruby 2.2 compatibility
|
111
187
|
|
112
188
|
## 1.2.0 - 2017-10-30
|
189
|
+
|
113
190
|
### Added
|
191
|
+
|
114
192
|
- Add experimental PooledEM adapter (#10)
|
115
193
|
|
116
194
|
### Changed
|
195
|
+
|
117
196
|
- Improve marshaling of resources
|
118
197
|
|
119
198
|
## 1.1.0 - 2017-05-12
|
199
|
+
|
120
200
|
### Added
|
201
|
+
|
121
202
|
- Add shortcuts for creating fulfilled / rejected promises (#6)
|
122
203
|
|
123
204
|
### Changed
|
205
|
+
|
124
206
|
- Return response body if no processor matches (#7)
|
125
207
|
|
126
208
|
## 1.0.0 - 2016-08-22
|
209
|
+
|
127
210
|
### Added
|
211
|
+
|
128
212
|
- Experimental cache API doing nothing for now
|
129
213
|
|
130
214
|
### Changed
|
215
|
+
|
131
216
|
- Use `~> 1.0` of `concurrent-ruby`
|
132
217
|
|
133
218
|
## 0.5.0 - 2016-04-04
|
219
|
+
|
134
220
|
### Added
|
221
|
+
|
135
222
|
- Add `sync` option to typhoeus adapter
|
136
223
|
- Add registry for storing entry points
|
137
224
|
|
138
225
|
### Changed
|
226
|
+
|
139
227
|
- Make eventmachine based adapter default
|
140
228
|
|
141
229
|
## 0.4.0 - 2016-02-24
|
230
|
+
|
142
231
|
### Added
|
232
|
+
|
143
233
|
- Add method to explicit access resource data
|
144
234
|
|
145
235
|
### Changed
|
236
|
+
|
146
237
|
- Use typhoeus as default adapter
|
147
238
|
- `Restify.new` returns relation now instead of resource
|
148
239
|
|
149
240
|
### Removed
|
241
|
+
|
150
242
|
- Drop obligation in favor of simple Concurrent::IVar based promise class.
|
151
243
|
Notable changes:
|
152
244
|
- Returned object us of type `Restify::Promise` now.
|
data/lib/restify/adapter/em.rb
CHANGED
@@ -29,7 +29,7 @@ module Restify
|
|
29
29
|
end
|
30
30
|
|
31
31
|
# rubocop:disable Style/IdenticalConditionalBranches
|
32
|
-
def call(request, writer, retried
|
32
|
+
def call(request, writer, retried: false)
|
33
33
|
if requests.empty?
|
34
34
|
requests << [request, writer, retried]
|
35
35
|
process_next
|
@@ -47,10 +47,6 @@ module Restify
|
|
47
47
|
@pipeline
|
48
48
|
end
|
49
49
|
|
50
|
-
# rubocop:disable Metrics/AbcSize
|
51
|
-
# rubocop:disable Metrics/CyclomaticComplexity
|
52
|
-
# rubocop:disable Metrics/MethodLength
|
53
|
-
# rubocop:disable Metrics/PerceivedComplexity
|
54
50
|
def process_next
|
55
51
|
return if requests.empty?
|
56
52
|
|
@@ -77,7 +73,7 @@ module Restify
|
|
77
73
|
req.last_effective_url,
|
78
74
|
req.response_header.status,
|
79
75
|
req.response_header,
|
80
|
-
req.response
|
76
|
+
req.response,
|
81
77
|
)
|
82
78
|
|
83
79
|
if req.response_header['CONNECTION'] == 'close'
|
@@ -108,7 +104,6 @@ module Restify
|
|
108
104
|
end
|
109
105
|
end
|
110
106
|
end
|
111
|
-
# rubocop:enable all
|
112
107
|
end
|
113
108
|
|
114
109
|
def call_native(request, writer)
|
@@ -128,12 +123,10 @@ module Restify
|
|
128
123
|
return if EventMachine.reactor_running?
|
129
124
|
|
130
125
|
Thread.new do
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
raise e
|
136
|
-
end
|
126
|
+
EventMachine.run
|
127
|
+
rescue StandardError => e
|
128
|
+
puts "#{self.class} -> #{e}\n#{e.backtrace.join("\n")}"
|
129
|
+
raise e
|
137
130
|
end
|
138
131
|
end
|
139
132
|
end
|
@@ -63,7 +63,7 @@ module Restify
|
|
63
63
|
#
|
64
64
|
def release(conn)
|
65
65
|
@available.unshift(conn) if @available.size < @size
|
66
|
-
@used -= 1 if @used
|
66
|
+
@used -= 1 if @used.positive?
|
67
67
|
|
68
68
|
logger.debug do
|
69
69
|
"[#{conn.uri}] Released to pool (#{@available.size}/#{@used}/#{size})"
|
@@ -97,7 +97,7 @@ module Restify
|
|
97
97
|
private
|
98
98
|
|
99
99
|
def close(conn)
|
100
|
-
@used -= 1 if @used
|
100
|
+
@used -= 1 if @used.positive?
|
101
101
|
@host[conn.uri.to_s] -= 1
|
102
102
|
|
103
103
|
conn.close
|
@@ -164,7 +164,7 @@ module Restify
|
|
164
164
|
def new(origin)
|
165
165
|
logger.debug do
|
166
166
|
"Connect to '#{origin}' " \
|
167
|
-
|
167
|
+
"(#{@connect_timeout}/#{@inactivity_timeout})..."
|
168
168
|
end
|
169
169
|
|
170
170
|
@host[origin] += 1
|
@@ -197,11 +197,10 @@ module Restify
|
|
197
197
|
end
|
198
198
|
|
199
199
|
def initialize(**kwargs)
|
200
|
+
super()
|
200
201
|
@pool = Pool.new(**kwargs)
|
201
202
|
end
|
202
203
|
|
203
|
-
# rubocop:disable Metrics/MethodLength
|
204
|
-
# rubocop:disable Metrics/AbcSize
|
205
204
|
# rubocop:disable Metrics/BlockLength
|
206
205
|
def call_native(request, writer)
|
207
206
|
next_tick do
|
@@ -212,39 +211,37 @@ module Restify
|
|
212
211
|
end
|
213
212
|
|
214
213
|
defer.callback do |conn|
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
if req.response_header['CONNECTION'] == 'close'
|
234
|
-
@pool.remove(conn)
|
235
|
-
else
|
236
|
-
@pool << conn
|
237
|
-
end
|
238
|
-
end
|
239
|
-
|
240
|
-
req.errback do
|
214
|
+
req = conn.send request.method.downcase,
|
215
|
+
keepalive: true,
|
216
|
+
redirects: 3,
|
217
|
+
path: request.uri.normalized_path,
|
218
|
+
query: request.uri.normalized_query,
|
219
|
+
body: request.body,
|
220
|
+
head: request.headers
|
221
|
+
|
222
|
+
req.callback do
|
223
|
+
writer.fulfill Response.new(
|
224
|
+
request,
|
225
|
+
req.last_effective_url,
|
226
|
+
req.response_header.status,
|
227
|
+
req.response_header,
|
228
|
+
req.response,
|
229
|
+
)
|
230
|
+
|
231
|
+
if req.response_header['CONNECTION'] == 'close'
|
241
232
|
@pool.remove(conn)
|
242
|
-
|
233
|
+
else
|
234
|
+
@pool << conn
|
243
235
|
end
|
244
|
-
|
236
|
+
end
|
237
|
+
|
238
|
+
req.errback do
|
245
239
|
@pool.remove(conn)
|
246
|
-
writer.reject(
|
240
|
+
writer.reject(req.error)
|
247
241
|
end
|
242
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
243
|
+
@pool.remove(conn)
|
244
|
+
writer.reject(e)
|
248
245
|
end
|
249
246
|
end
|
250
247
|
end
|
@@ -261,12 +258,10 @@ module Restify
|
|
261
258
|
return if EventMachine.reactor_running?
|
262
259
|
|
263
260
|
Thread.new do
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
raise e
|
269
|
-
end
|
261
|
+
EventMachine.run
|
262
|
+
rescue StandardError => e
|
263
|
+
logger.error(e)
|
264
|
+
raise e
|
270
265
|
end
|
271
266
|
end
|
272
267
|
end
|
@@ -13,60 +13,52 @@ module Restify
|
|
13
13
|
|
14
14
|
DEFAULT_HEADERS = {
|
15
15
|
'Expect' => '',
|
16
|
-
'Transfer-Encoding' => ''
|
16
|
+
'Transfer-Encoding' => '',
|
17
17
|
}.freeze
|
18
18
|
|
19
19
|
DEFAULT_OPTIONS = {
|
20
20
|
followlocation: true,
|
21
21
|
tcp_keepalive: true,
|
22
22
|
tcp_keepidle: 5,
|
23
|
-
tcp_keepintvl: 5
|
23
|
+
tcp_keepintvl: 5,
|
24
24
|
}.freeze
|
25
25
|
|
26
26
|
def initialize(sync: false, options: {}, **kwargs)
|
27
|
-
@sync = sync
|
28
27
|
@hydra = ::Typhoeus::Hydra.new(**kwargs)
|
29
28
|
@mutex = Mutex.new
|
30
|
-
@signal = ConditionVariable.new
|
31
|
-
@thread = nil
|
32
29
|
@options = DEFAULT_OPTIONS.merge(options)
|
30
|
+
@queue = Queue.new
|
31
|
+
@sync = sync
|
32
|
+
@thread = nil
|
33
|
+
|
34
|
+
super()
|
33
35
|
end
|
34
36
|
|
35
37
|
def sync?
|
36
38
|
@sync
|
37
39
|
end
|
38
40
|
|
39
|
-
# rubocop:disable Metrics/AbcSize
|
40
|
-
# rubocop:disable Metrics/MethodLength
|
41
41
|
def call_native(request, writer)
|
42
42
|
req = convert(request, writer)
|
43
43
|
|
44
44
|
if sync?
|
45
|
-
req
|
45
|
+
@hydra.queue(req)
|
46
|
+
@hydra.run
|
46
47
|
else
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
@hydra.queue(req)
|
54
|
-
@hydra.dequeue_many
|
55
|
-
|
56
|
-
thread.run unless thread.status
|
57
|
-
end
|
48
|
+
debug 'request:add',
|
49
|
+
tag: request.object_id,
|
50
|
+
method: request.method.upcase,
|
51
|
+
url: request.uri,
|
52
|
+
timeout: request.timeout
|
58
53
|
|
59
|
-
|
54
|
+
@queue << convert(request, writer)
|
60
55
|
|
61
|
-
|
56
|
+
thread.run unless thread.status
|
62
57
|
end
|
63
58
|
end
|
64
|
-
# rubocop:enable all
|
65
59
|
|
66
60
|
private
|
67
61
|
|
68
|
-
# rubocop:disable Metrics/AbcSize
|
69
|
-
# rubocop:disable Metrics/MethodLength
|
70
62
|
def convert(request, writer)
|
71
63
|
::Typhoeus::Request.new(
|
72
64
|
request.uri,
|
@@ -75,25 +67,28 @@ module Restify
|
|
75
67
|
headers: DEFAULT_HEADERS.merge(request.headers),
|
76
68
|
body: request.body,
|
77
69
|
timeout: request.timeout,
|
78
|
-
connecttimeout: request.timeout
|
70
|
+
connecttimeout: request.timeout,
|
79
71
|
).tap do |req|
|
80
72
|
req.on_complete do |response|
|
81
73
|
debug 'request:complete',
|
82
74
|
tag: request.object_id,
|
83
|
-
status: response.code
|
75
|
+
status: response.code,
|
76
|
+
message: response.return_message,
|
77
|
+
timeout: response.timed_out?
|
84
78
|
|
85
|
-
if response.timed_out?
|
86
|
-
writer.reject Restify::Timeout.new request
|
87
|
-
elsif response.code.zero?
|
79
|
+
if response.timed_out? || response.code.zero?
|
88
80
|
writer.reject \
|
89
81
|
Restify::NetworkError.new(request, response.return_message)
|
90
82
|
else
|
91
83
|
writer.fulfill convert_back(response, request)
|
92
84
|
end
|
85
|
+
|
86
|
+
# Add all newly queued requests to active hydra, e.g. requests
|
87
|
+
# queued in a completion callback.
|
88
|
+
dequeue_all
|
93
89
|
end
|
94
90
|
end
|
95
91
|
end
|
96
|
-
# rubocop:enable all
|
97
92
|
|
98
93
|
def convert_back(response, request)
|
99
94
|
uri = request.uri
|
@@ -117,38 +112,49 @@ module Restify
|
|
117
112
|
# Recreate thread if nil or dead
|
118
113
|
debug 'hydra:spawn'
|
119
114
|
|
120
|
-
@thread = Thread.new
|
115
|
+
@thread = Thread.new do
|
116
|
+
Thread.current.name = 'Restify/Typhoeus Background'
|
117
|
+
run
|
118
|
+
end
|
121
119
|
end
|
122
120
|
|
123
121
|
@thread
|
124
122
|
end
|
125
123
|
|
126
|
-
def
|
127
|
-
|
128
|
-
loop { _run }
|
129
|
-
end
|
124
|
+
def run
|
125
|
+
runs = 0
|
130
126
|
|
131
|
-
|
132
|
-
|
133
|
-
|
127
|
+
loop do
|
128
|
+
if @queue.empty? && runs > 100
|
129
|
+
debug 'hydra:gc'
|
130
|
+
GC.start(full_mark: false, immediate_sweep: false)
|
131
|
+
runs = 0
|
132
|
+
end
|
133
|
+
|
134
|
+
debug 'hydra:pop'
|
134
135
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
@hydra.run while _ongoing?
|
139
|
-
debug 'hydra:completed'
|
136
|
+
# Wait for next item and add all available requests to hydra
|
137
|
+
@hydra.queue @queue.pop
|
138
|
+
dequeue_all
|
140
139
|
|
141
|
-
|
142
|
-
|
140
|
+
debug 'hydra:run'
|
141
|
+
@hydra.run
|
142
|
+
runs += 1
|
143
|
+
debug 'hydra:completed'
|
144
|
+
rescue StandardError => e
|
145
|
+
logger.error(e)
|
146
|
+
end
|
147
|
+
ensure
|
148
|
+
debug 'hydra:exit'
|
149
|
+
end
|
143
150
|
|
144
|
-
|
145
|
-
|
146
|
-
|
151
|
+
def dequeue_all
|
152
|
+
loop do
|
153
|
+
@hydra.queue @queue.pop(true)
|
154
|
+
rescue ThreadError
|
155
|
+
break
|
147
156
|
end
|
148
|
-
rescue StandardError => e
|
149
|
-
logger.error(e)
|
150
157
|
end
|
151
|
-
# rubocop:enable all
|
152
158
|
|
153
159
|
def _log_prefix
|
154
160
|
"[#{object_id}/#{Thread.current.object_id}]"
|
data/lib/restify/context.rb
CHANGED
@@ -47,26 +47,22 @@ module Restify
|
|
47
47
|
processor.new(context, response).resource
|
48
48
|
end
|
49
49
|
|
50
|
-
# rubocop:disable Metrics/MethodLength
|
51
50
|
def request(method, uri, data: nil, headers: {}, **kwargs)
|
52
51
|
request = Request.new(
|
53
52
|
headers: default_headers.merge(headers),
|
54
53
|
**kwargs,
|
55
54
|
method: method,
|
56
55
|
uri: join(uri),
|
57
|
-
data: data
|
56
|
+
data: data,
|
58
57
|
)
|
59
58
|
|
60
59
|
ret = cache.call(request) {|req| adapter.call(req) }
|
61
60
|
ret.then do |response|
|
62
|
-
if
|
63
|
-
|
64
|
-
|
65
|
-
raise ResponseError.from_code(response)
|
66
|
-
end
|
61
|
+
raise ResponseError.from_code(response) if response.errored?
|
62
|
+
|
63
|
+
process(response)
|
67
64
|
end
|
68
65
|
end
|
69
|
-
# rubocop:enable all
|
70
66
|
|
71
67
|
def encode_with(coder)
|
72
68
|
coder.map = marshal_dump
|
@@ -79,7 +75,7 @@ module Restify
|
|
79
75
|
def marshal_dump
|
80
76
|
{
|
81
77
|
uri: uri.to_s,
|
82
|
-
headers: default_headers
|
78
|
+
headers: default_headers,
|
83
79
|
}
|
84
80
|
end
|
85
81
|
|
data/lib/restify/error.rb
CHANGED
@@ -34,6 +34,8 @@ module Restify
|
|
34
34
|
Gone.new(response)
|
35
35
|
when 422
|
36
36
|
UnprocessableEntity.new(response)
|
37
|
+
when 429
|
38
|
+
TooManyRequests.new(response)
|
37
39
|
when 400...500
|
38
40
|
ClientError.new(response)
|
39
41
|
when 500
|
@@ -110,15 +112,37 @@ module Restify
|
|
110
112
|
# This makes it easy to rescue specific expected error types.
|
111
113
|
|
112
114
|
class BadRequest < ClientError; end
|
115
|
+
|
113
116
|
class Unauthorized < ClientError; end
|
117
|
+
|
114
118
|
class NotFound < ClientError; end
|
119
|
+
|
115
120
|
class NotAcceptable < ClientError; end
|
121
|
+
|
116
122
|
class Gone < ClientError; end
|
123
|
+
|
117
124
|
class UnprocessableEntity < ClientError; end
|
118
125
|
|
126
|
+
class TooManyRequests < ClientError
|
127
|
+
def retry_after
|
128
|
+
case response.headers['RETRY_AFTER']
|
129
|
+
when /^\d+$/
|
130
|
+
DateTime.now + Rational(response.headers['RETRY_AFTER'].to_i, 86_400)
|
131
|
+
when String
|
132
|
+
begin
|
133
|
+
DateTime.httpdate response.headers['RETRY_AFTER']
|
134
|
+
rescue ArgumentError
|
135
|
+
nil
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
119
141
|
class InternalServerError < ServerError; end
|
120
142
|
|
121
143
|
class BadGateway < GatewayError; end
|
144
|
+
|
122
145
|
class ServiceUnavailable < GatewayError; end
|
146
|
+
|
123
147
|
class GatewayTimeout < GatewayError; end
|
124
148
|
end
|