restify 1.15.2 → 2.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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +25 -2
  3. data/README.md +23 -31
  4. data/lib/restify/adapter/base.rb +4 -0
  5. data/lib/restify/adapter/telemetry.rb +54 -0
  6. data/lib/restify/adapter/typhoeus.rb +21 -3
  7. data/lib/restify/context.rb +3 -3
  8. data/lib/restify/error.rb +2 -2
  9. data/lib/restify/link.rb +4 -4
  10. data/lib/restify/processors/base/parsing.rb +2 -21
  11. data/lib/restify/processors/base.rb +1 -1
  12. data/lib/restify/promise.rb +2 -2
  13. data/lib/restify/registry.rb +1 -1
  14. data/lib/restify/relation.rb +45 -17
  15. data/lib/restify/request.rb +6 -6
  16. data/lib/restify/timeout.rb +2 -2
  17. data/lib/restify/version.rb +3 -3
  18. data/lib/restify.rb +0 -1
  19. data/spec/restify/cache_spec.rb +16 -12
  20. data/spec/restify/context_spec.rb +8 -3
  21. data/spec/restify/error_spec.rb +13 -16
  22. data/spec/restify/features/head_requests_spec.rb +5 -4
  23. data/spec/restify/features/request_bodies_spec.rb +8 -8
  24. data/spec/restify/features/request_errors_spec.rb +2 -2
  25. data/spec/restify/features/request_headers_spec.rb +3 -6
  26. data/spec/restify/features/response_errors_spec.rb +1 -1
  27. data/spec/restify/global_spec.rb +10 -10
  28. data/spec/restify/processors/base_spec.rb +6 -7
  29. data/spec/restify/processors/json_spec.rb +21 -62
  30. data/spec/restify/processors/msgpack_spec.rb +33 -70
  31. data/spec/restify/promise_spec.rb +31 -31
  32. data/spec/restify/registry_spec.rb +5 -7
  33. data/spec/restify/relation_spec.rb +185 -7
  34. data/spec/restify/resource_spec.rb +47 -53
  35. data/spec/restify/timeout_spec.rb +3 -3
  36. data/spec/restify_spec.rb +12 -73
  37. data/spec/spec_helper.rb +11 -15
  38. metadata +33 -64
  39. data/lib/restify/adapter/em.rb +0 -134
  40. data/lib/restify/adapter/pooled_em.rb +0 -269
@@ -1,269 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'eventmachine'
4
- require 'em-http-request'
5
-
6
- module Restify
7
- module Adapter
8
- class PooledEM < Base
9
- include Logging
10
-
11
- # This class maintains a pool of connection objects, grouped by origin,
12
- # and ensures limits for total parallel requests and per-origin requests.
13
- #
14
- # It does so by maintaining a list of already open, reusable connections.
15
- # When any of them are checked out for usage, it counts the usages to
16
- # prevent constraints being broken.
17
- class Pool
18
- include Logging
19
-
20
- def initialize(size: 32, per_host: 6, connect_timeout: 2, inactivity_timeout: 10)
21
- @size = size
22
- @per_host = per_host
23
- @connect_timeout = connect_timeout
24
- @inactivity_timeout = inactivity_timeout
25
-
26
- @host = Hash.new {|h, k| h[k] = 0 }
27
- @available = []
28
- @queue = []
29
- @used = 0
30
- end
31
-
32
- # Request a connection from the pool.
33
- #
34
- # Attempts to checkout a reusable connection from the pool (or create a
35
- # new one). If any of the limits have been reached, the request will be
36
- # put onto a queue until other connections are released.
37
- #
38
- # Returns a Deferrable that succeeds with a connection instance once a
39
- # connection has been checked out (usually immediately).
40
- #
41
- # @return [Deferrable<Request>]
42
- #
43
- def get(request, timeout: 2)
44
- defer = Deferrable.new(request)
45
- defer.timeout(timeout, :timeout)
46
- defer.errback { @queue.delete(defer) }
47
-
48
- checkout(defer)
49
-
50
- defer
51
- end
52
-
53
- # Return a connection to the pool.
54
- #
55
- # If there are requests in the queue (due to one of the limits having
56
- # been reached), they will be given an attempt to use the released
57
- # connection.
58
- #
59
- # If no requests are queued, the connection will be held for reuse by a
60
- # subsequent request.
61
- #
62
- # @return [void]
63
- #
64
- def release(conn)
65
- @available.unshift(conn) if @available.size < @size
66
- @used -= 1 if @used.positive?
67
-
68
- logger.debug do
69
- "[#{conn.uri}] Released to pool (#{@available.size}/#{@used}/#{size})"
70
- end
71
-
72
- checkout(@queue.shift) if @queue.any? # checkout next waiting defer
73
- end
74
-
75
- alias << release
76
-
77
- def remove(conn)
78
- close(conn)
79
-
80
- logger.debug do
81
- "[#{conn.uri}] Removed from pool (#{@available.size}/#{@used}/#{size})"
82
- end
83
-
84
- checkout(@queue.shift) if @queue.any? # checkout next waiting defer
85
- end
86
-
87
- # Determine the number of connections in the pool.
88
- #
89
- # This takes into account both reusable (idle) and used connections.
90
- #
91
- # @return [Integer]
92
- #
93
- def size
94
- @available.size + @used
95
- end
96
-
97
- private
98
-
99
- def close(conn)
100
- @used -= 1 if @used.positive?
101
- @host[conn.uri.to_s] -= 1
102
-
103
- conn.close
104
- end
105
-
106
- def checkout(defer)
107
- origin = defer.request.uri.origin
108
-
109
- if (index = find_reusable_connection(origin))
110
- defer.succeed reuse_connection(index, origin)
111
- elsif can_build_new_connection?(origin)
112
- defer.succeed new_connection(origin)
113
- else
114
- queue defer
115
- end
116
- end
117
-
118
- def find_reusable_connection(origin)
119
- @available.find_index {|conn| conn.uri == origin }
120
- end
121
-
122
- def reuse_connection(index, origin)
123
- @used += 1
124
- @available.delete_at(index).tap do
125
- logger.debug do
126
- "[#{origin}] Take connection from pool " \
127
- "(#{@available.size}/#{@used}/#{size})"
128
- end
129
- end
130
- end
131
-
132
- def new_connection(origin)
133
- # If we have reached the limit, we have to throw away the oldest
134
- # reusable connection in order to open a new one
135
- close_oldest if size >= @size
136
-
137
- @used += 1
138
- new(origin).tap do
139
- logger.debug do
140
- "[#{origin}] Add new connection to pool " \
141
- "(#{@available.size}/#{@used}/#{size})"
142
- end
143
- end
144
- end
145
-
146
- def close_oldest
147
- close(@available.pop)
148
-
149
- logger.debug do
150
- "[#{origin}] Closed oldest connection in pool " \
151
- "(#{@available.size}/#{@used}/#{size})"
152
- end
153
- end
154
-
155
- def queue(defer)
156
- logger.debug do
157
- "[#{origin}] Wait for free slot " \
158
- "(#{@available.size}/#{@used}/#{size})"
159
- end
160
-
161
- @queue << defer
162
- end
163
-
164
- def new(origin)
165
- logger.debug do
166
- "Connect to '#{origin}' " \
167
- "(#{@connect_timeout}/#{@inactivity_timeout})..."
168
- end
169
-
170
- @host[origin] += 1
171
-
172
- EventMachine::HttpRequest.new origin,
173
- connect_timeout: @connect_timeout,
174
- inactivity_timeout: @inactivity_timeout
175
- end
176
-
177
- def can_build_new_connection?(origin)
178
- return false if @host[origin] >= @per_host
179
-
180
- size < @size || @available.any?
181
- end
182
-
183
- class Deferrable
184
- include ::EventMachine::Deferrable
185
-
186
- attr_reader :request
187
-
188
- def initialize(request)
189
- @request = request
190
- end
191
-
192
- def succeed(connection)
193
- @connection = connection
194
- super
195
- end
196
- end
197
- end
198
-
199
- def initialize(**kwargs)
200
- super()
201
- @pool = Pool.new(**kwargs)
202
- end
203
-
204
- # rubocop:disable Metrics/BlockLength
205
- def call_native(request, writer)
206
- next_tick do
207
- defer = @pool.get(request)
208
-
209
- defer.errback do |error|
210
- writer.reject(error)
211
- end
212
-
213
- defer.callback do |conn|
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'
232
- @pool.remove(conn)
233
- else
234
- @pool << conn
235
- end
236
- end
237
-
238
- req.errback do
239
- @pool.remove(conn)
240
- writer.reject(req.error)
241
- end
242
- rescue Exception => e # rubocop:disable Lint/RescueException
243
- @pool.remove(conn)
244
- writer.reject(e)
245
- end
246
- end
247
- end
248
- # rubocop:enable all
249
-
250
- private
251
-
252
- def next_tick(&block)
253
- ensure_running
254
- EventMachine.next_tick(&block)
255
- end
256
-
257
- def ensure_running
258
- return if EventMachine.reactor_running?
259
-
260
- Thread.new do
261
- EventMachine.run
262
- rescue StandardError => e
263
- logger.error(e)
264
- raise e
265
- end
266
- end
267
- end
268
- end
269
- end