raptor 0.22.3 → 0.23.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 +4 -4
- data/CHANGELOG.md +30 -0
- data/Dockerfile +3 -1
- data/README.md +38 -31
- data/docs/raptor-vs-puma.md +44 -38
- data/docs/talk.md +1295 -0
- data/ext/raptor_bpf/reuseport_select.bpf.c +18 -9
- data/ext/raptor_http/extconf.rb +2 -0
- data/ext/raptor_http/raptor_http.c +91 -119
- data/ext/raptor_http2/raptor_http2.c +272 -223
- data/ext/raptor_native/raptor_native.c +38 -20
- data/lib/rackup/handler/raptor.rb +12 -11
- data/lib/raptor/binder.rb +12 -12
- data/lib/raptor/cli.rb +18 -18
- data/lib/raptor/cluster.rb +44 -44
- data/lib/raptor/control_server.rb +3 -2
- data/lib/raptor/detached_body.rb +6 -2
- data/lib/raptor/http.rb +7 -5
- data/lib/raptor/http1.rb +232 -207
- data/lib/raptor/http2.rb +312 -265
- data/lib/raptor/reactor.rb +138 -148
- data/lib/raptor/reuseport_bpf.rb +62 -38
- data/lib/raptor/server.rb +45 -34
- data/lib/raptor/stats.rb +15 -3
- data/lib/raptor/thread_locals.rb +4 -3
- data/lib/raptor/version.rb +1 -1
- data/sig/generated/rackup/handler/raptor.rbs +2 -1
- data/sig/generated/raptor/binder.rbs +9 -9
- data/sig/generated/raptor/cli.rbs +6 -6
- data/sig/generated/raptor/cluster.rbs +9 -9
- data/sig/generated/raptor/control_server.rbs +2 -1
- data/sig/generated/raptor/detached_body.rbs +5 -1
- data/sig/generated/raptor/http.rbs +3 -3
- data/sig/generated/raptor/http1.rbs +100 -91
- data/sig/generated/raptor/http2.rbs +200 -189
- data/sig/generated/raptor/reactor.rbs +107 -118
- data/sig/generated/raptor/reuseport_bpf.rbs +54 -17
- data/sig/generated/raptor/server.rbs +26 -26
- data/sig/generated/raptor/stats.rbs +3 -2
- data/sig/generated/raptor/thread_locals.rbs +4 -3
- metadata +2 -2
- data/docs/brisrails-talk.md +0 -2398
data/lib/raptor/reactor.rb
CHANGED
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
# rbs_inline: enabled
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
|
-
require "nio"
|
|
5
4
|
require "openssl"
|
|
6
|
-
require "red-black-tree"
|
|
7
5
|
require "timeout"
|
|
8
6
|
|
|
9
7
|
require "atomic-ruby/atom"
|
|
10
8
|
require "atomic-ruby/atomic_boolean"
|
|
11
9
|
require "atomic-ruby/atomic_condition_variable"
|
|
12
10
|
require "atomic-ruby/atomic_queue"
|
|
11
|
+
require "atomic-ruby/atomic_thread_pool"
|
|
12
|
+
require "nio"
|
|
13
|
+
require "red-black-tree"
|
|
13
14
|
|
|
14
15
|
require_relative "detached_body"
|
|
15
16
|
require_relative "http1"
|
|
16
17
|
require_relative "http2"
|
|
17
18
|
require_relative "log"
|
|
19
|
+
require_relative "raptor_http2"
|
|
18
20
|
|
|
19
21
|
module Raptor
|
|
20
22
|
# Multiplexes client connections, manages connection deadlines, feeds
|
|
@@ -22,12 +24,18 @@ module Raptor
|
|
|
22
24
|
# to the caller-provided handlers.
|
|
23
25
|
#
|
|
24
26
|
class Reactor
|
|
27
|
+
CHUNK_SIZE = 64 * 1024
|
|
28
|
+
DETACHED_CONNECTION_BUFFER_SIZE = 1024 * 1024
|
|
29
|
+
DETACHED_WRITE_BATCH = 8
|
|
30
|
+
DETACHED_WORKER_BUFFER_SIZE = 16 * 1024 * 1024
|
|
31
|
+
|
|
32
|
+
TIMEOUT_RESPONSE = "HTTP/1.1 408 Request Timeout\r\nContent-Length: 0\r\nConnection: close\r\n\r\n"
|
|
33
|
+
|
|
25
34
|
# A client connection node ordered by absolute expiry time so the
|
|
26
35
|
# soonest-to-expire is always at the tree's minimum.
|
|
27
36
|
#
|
|
28
37
|
class TimeoutClient < RedBlackTree::Node
|
|
29
|
-
|
|
30
|
-
attr_accessor :timeout_at
|
|
38
|
+
attr_accessor :timeout_at #: Float
|
|
31
39
|
|
|
32
40
|
# Returns the client connection state.
|
|
33
41
|
#
|
|
@@ -46,7 +54,7 @@ module Raptor
|
|
|
46
54
|
#
|
|
47
55
|
# @rbs (Float now) -> Float
|
|
48
56
|
def timeout(now)
|
|
49
|
-
[timeout_at - now, 0].max
|
|
57
|
+
[timeout_at - now, 0.0].max
|
|
50
58
|
end
|
|
51
59
|
|
|
52
60
|
# Orders nodes by `timeout_at` so the tree minimum is the next
|
|
@@ -64,26 +72,13 @@ module Raptor
|
|
|
64
72
|
# Tracks reactor-owned output state for a connection.
|
|
65
73
|
#
|
|
66
74
|
class ConnectionIO
|
|
67
|
-
|
|
68
|
-
attr_accessor :
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
attr_accessor :
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
attr_accessor :reading
|
|
75
|
-
|
|
76
|
-
# @rbs attr_accessor closing: bool
|
|
77
|
-
attr_accessor :closing
|
|
78
|
-
|
|
79
|
-
# @rbs attr_accessor monitor: NIO::Monitor?
|
|
80
|
-
attr_accessor :monitor
|
|
81
|
-
|
|
82
|
-
# @rbs attr_accessor timeout: TimeoutClient?
|
|
83
|
-
attr_accessor :timeout
|
|
84
|
-
|
|
85
|
-
# @rbs attr_reader output: Array[String]
|
|
86
|
-
attr_reader :output
|
|
75
|
+
attr_accessor :offset #: Integer
|
|
76
|
+
attr_accessor :wait #: Symbol?
|
|
77
|
+
attr_accessor :reading #: bool
|
|
78
|
+
attr_accessor :closing #: bool
|
|
79
|
+
attr_accessor :monitor #: NIO::Monitor?
|
|
80
|
+
attr_accessor :timeout #: TimeoutClient?
|
|
81
|
+
attr_reader :output #: Array[String]
|
|
87
82
|
|
|
88
83
|
# Creates empty connection I/O state for reactor-owned writes.
|
|
89
84
|
#
|
|
@@ -113,25 +108,16 @@ module Raptor
|
|
|
113
108
|
# Tracks reactor-owned I/O state for an HTTP/1.x detached response.
|
|
114
109
|
#
|
|
115
110
|
class Http1IO < ConnectionIO
|
|
116
|
-
|
|
117
|
-
attr_accessor :
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
# @rbs attr_reader budget: DetachedBody::Budget
|
|
123
|
-
attr_reader :budget
|
|
124
|
-
|
|
125
|
-
# @rbs attr_reader input: String
|
|
126
|
-
attr_reader :input
|
|
127
|
-
|
|
128
|
-
# @rbs attr_reader state: Hash[Symbol, untyped]
|
|
129
|
-
attr_reader :state
|
|
111
|
+
attr_accessor :body #: DetachedBody?
|
|
112
|
+
attr_accessor :finishing #: bool
|
|
113
|
+
attr_reader :budget #: DetachedBody::Budget
|
|
114
|
+
attr_reader :input #: String
|
|
115
|
+
attr_reader :state #: Hash[Symbol, untyped]
|
|
130
116
|
|
|
131
117
|
# Creates I/O state for an HTTP/1.x detached response.
|
|
132
118
|
#
|
|
133
119
|
# @param body [DetachedBody] the response body
|
|
134
|
-
# @param state [Hash] connection state restored after the response finishes
|
|
120
|
+
# @param state [Hash] connection state restored after the response finishes, including bytes the client pipelined after the request
|
|
135
121
|
# @return [void]
|
|
136
122
|
#
|
|
137
123
|
# @rbs (DetachedBody body, Hash[Symbol, untyped] state) -> void
|
|
@@ -140,7 +126,7 @@ module Raptor
|
|
|
140
126
|
@body = body
|
|
141
127
|
@state = state
|
|
142
128
|
@budget = DetachedBody::Budget.new(DETACHED_CONNECTION_BUFFER_SIZE)
|
|
143
|
-
@input = String.new(encoding: Encoding::ASCII_8BIT)
|
|
129
|
+
@input = String.new(state[:pipelined] || "", encoding: Encoding::ASCII_8BIT)
|
|
144
130
|
@reading = true
|
|
145
131
|
@finishing = false
|
|
146
132
|
end
|
|
@@ -158,17 +144,10 @@ module Raptor
|
|
|
158
144
|
# Tracks reactor-owned I/O state for an HTTP/2 connection.
|
|
159
145
|
#
|
|
160
146
|
class Http2IO < ConnectionIO
|
|
161
|
-
|
|
162
|
-
attr_reader :
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
attr_reader :ready
|
|
166
|
-
|
|
167
|
-
# @rbs attr_reader ready_streams: Hash[Integer, bool]
|
|
168
|
-
attr_reader :ready_streams
|
|
169
|
-
|
|
170
|
-
# @rbs attr_reader budget: DetachedBody::Budget
|
|
171
|
-
attr_reader :budget
|
|
147
|
+
attr_reader :detached #: Hash[Integer, DetachedBody]
|
|
148
|
+
attr_reader :ready #: Array[Integer]
|
|
149
|
+
attr_reader :ready_streams #: Hash[Integer, bool]
|
|
150
|
+
attr_reader :budget #: DetachedBody::Budget
|
|
172
151
|
|
|
173
152
|
# Creates empty I/O state for an HTTP/2 connection and its detached streams.
|
|
174
153
|
#
|
|
@@ -193,19 +172,14 @@ module Raptor
|
|
|
193
172
|
end
|
|
194
173
|
end
|
|
195
174
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
TIMEOUT_RESPONSE = "HTTP/1.1 408 Request Timeout\r\nContent-Length: 0\r\nConnection: close\r\n\r\n"
|
|
201
|
-
|
|
202
|
-
# @rbs @thread_pool: untyped
|
|
203
|
-
# @rbs @http1_ractor_pool: untyped
|
|
204
|
-
# @rbs @http2_ractor_pool: untyped
|
|
175
|
+
# @rbs @http1: Http1
|
|
176
|
+
# @rbs @http1_ractor_pool: RactorPool
|
|
177
|
+
# @rbs @http2_ractor_pool: RactorPool?
|
|
178
|
+
# @rbs @thread_pool: AtomicThreadPool
|
|
205
179
|
# @rbs @first_data_timeout: Integer
|
|
206
180
|
# @rbs @chunk_data_timeout: Integer
|
|
207
|
-
# @rbs @persistent_data_timeout: Integer
|
|
208
181
|
# @rbs @write_timeout: Integer
|
|
182
|
+
# @rbs @persistent_data_timeout: Integer
|
|
209
183
|
# @rbs @http2_keepalive_interval: Integer
|
|
210
184
|
# @rbs @http2_keepalive_timeout: Integer
|
|
211
185
|
# @rbs @selector: NIO::Selector
|
|
@@ -216,8 +190,8 @@ module Raptor
|
|
|
216
190
|
# @rbs @id_to_socket: Hash[Integer, TCPSocket]
|
|
217
191
|
# @rbs @socket_to_state: Hash[TCPSocket, Hash[Symbol, untyped]]
|
|
218
192
|
# @rbs @id_to_timeout: Hash[Integer, TimeoutClient]
|
|
219
|
-
# @rbs @id_to_writer: Hash[Integer,
|
|
220
|
-
# @rbs @id_to_flow_control: Hash[Integer,
|
|
193
|
+
# @rbs @id_to_writer: Hash[Integer, Http2::Writer]
|
|
194
|
+
# @rbs @id_to_flow_control: Hash[Integer, Http2::FlowControl]
|
|
221
195
|
# @rbs @id_to_http2_last_stream: Hash[Integer, Integer]
|
|
222
196
|
# @rbs @id_to_http2_drain_stream: Hash[Integer, Integer]
|
|
223
197
|
# @rbs @id_to_http2_keepalive: Hash[Integer, Hash[Symbol, untyped]]
|
|
@@ -227,8 +201,9 @@ module Raptor
|
|
|
227
201
|
# @rbs @detached_drained: AtomicConditionVariable
|
|
228
202
|
# @rbs @thread: Thread?
|
|
229
203
|
|
|
230
|
-
# Creates a new Reactor
|
|
204
|
+
# Creates a new Reactor.
|
|
231
205
|
#
|
|
206
|
+
# @param http1 [Http1] the HTTP/1.1 handler that resumes idle keep-alive connections
|
|
232
207
|
# @param http1_ractor_pool [RactorPool] ractor pool for HTTP/1.x parsing
|
|
233
208
|
# @param http2_ractor_pool [RactorPool, nil] ractor pool for HTTP/2 parsing, or nil when no listener supports HTTP/2
|
|
234
209
|
# @param thread_pool [AtomicThreadPool] thread pool for application processing
|
|
@@ -243,8 +218,9 @@ module Raptor
|
|
|
243
218
|
# @option http2_options [Integer] :keepalive_timeout time to await a PING acknowledgement
|
|
244
219
|
# @return [void]
|
|
245
220
|
#
|
|
246
|
-
# @rbs (
|
|
247
|
-
def initialize(http1_ractor_pool, http2_ractor_pool, thread_pool, connection_options:, http1_options:, http2_options:)
|
|
221
|
+
# @rbs (Http1 http1, RactorPool http1_ractor_pool, RactorPool? http2_ractor_pool, AtomicThreadPool thread_pool, connection_options: Hash[Symbol, untyped], http1_options: Hash[Symbol, untyped], http2_options: Hash[Symbol, untyped]) -> void
|
|
222
|
+
def initialize(http1, http1_ractor_pool, http2_ractor_pool, thread_pool, connection_options:, http1_options:, http2_options:)
|
|
223
|
+
@http1 = http1
|
|
248
224
|
@http1_ractor_pool = http1_ractor_pool
|
|
249
225
|
@http2_ractor_pool = http2_ractor_pool
|
|
250
226
|
@thread_pool = thread_pool
|
|
@@ -328,19 +304,14 @@ module Raptor
|
|
|
328
304
|
#
|
|
329
305
|
# @param state [Hash] client connection state including socket and ID
|
|
330
306
|
# @option state [TCPSocket] :socket the client socket
|
|
331
|
-
# @option state [Integer] :id unique identifier
|
|
307
|
+
# @option state [Integer] :id unique connection identifier
|
|
332
308
|
# @return [void]
|
|
333
309
|
#
|
|
334
310
|
# @rbs (Hash[Symbol, untyped] state) -> void
|
|
335
311
|
def add(state)
|
|
336
|
-
socket = state
|
|
337
|
-
state.delete(:socket)
|
|
338
|
-
writer = state.delete(:writer)
|
|
339
|
-
flow_control = state.delete(:flow_control)
|
|
312
|
+
socket = state.delete(:socket)
|
|
340
313
|
@id_to_socket[state[:id]] = socket
|
|
341
314
|
@socket_to_state[socket] = state
|
|
342
|
-
@id_to_writer[state[:id]] = writer if writer
|
|
343
|
-
@id_to_flow_control[state[:id]] = flow_control if flow_control
|
|
344
315
|
|
|
345
316
|
read_and_queue_for_parse(socket, state)
|
|
346
317
|
end
|
|
@@ -349,7 +320,7 @@ module Raptor
|
|
|
349
320
|
# it for further I/O.
|
|
350
321
|
#
|
|
351
322
|
# @param state [Hash] updated client connection state
|
|
352
|
-
# @option state [Integer] :id
|
|
323
|
+
# @option state [Integer] :id unique connection identifier
|
|
353
324
|
# @return [void]
|
|
354
325
|
#
|
|
355
326
|
# @rbs (Hash[Symbol, untyped] state) -> void
|
|
@@ -368,7 +339,7 @@ module Raptor
|
|
|
368
339
|
# has been handed off to the thread pool. The socket itself is kept
|
|
369
340
|
# open so the worker can write the response.
|
|
370
341
|
#
|
|
371
|
-
# @param id [Integer] unique
|
|
342
|
+
# @param id [Integer] unique connection identifier
|
|
372
343
|
# @return [TCPSocket, nil] the socket associated with `id`, if any
|
|
373
344
|
#
|
|
374
345
|
# @rbs (Integer id) -> TCPSocket?
|
|
@@ -382,9 +353,9 @@ module Raptor
|
|
|
382
353
|
# under the persistent-data timeout.
|
|
383
354
|
#
|
|
384
355
|
# @param socket [TCPSocket] the kept-alive client socket
|
|
385
|
-
# @param id [Integer]
|
|
356
|
+
# @param id [Integer] unique connection identifier
|
|
386
357
|
# @param request_count [Integer] number of requests handled on this connection
|
|
387
|
-
# @param remote_addr [String] the client
|
|
358
|
+
# @param remote_addr [String] the client IP address
|
|
388
359
|
# @param url_scheme [String] "http" or "https"
|
|
389
360
|
# @return [void]
|
|
390
361
|
#
|
|
@@ -406,9 +377,9 @@ module Raptor
|
|
|
406
377
|
socket.close
|
|
407
378
|
end
|
|
408
379
|
|
|
409
|
-
# Returns the socket for a given
|
|
380
|
+
# Returns the socket for a given connection identifier without removing it.
|
|
410
381
|
#
|
|
411
|
-
# @param id [Integer] unique
|
|
382
|
+
# @param id [Integer] unique connection identifier
|
|
412
383
|
# @return [TCPSocket, nil] the socket, if found
|
|
413
384
|
#
|
|
414
385
|
# @rbs (Integer id) -> TCPSocket?
|
|
@@ -416,24 +387,24 @@ module Raptor
|
|
|
416
387
|
@id_to_socket[id]
|
|
417
388
|
end
|
|
418
389
|
|
|
419
|
-
# Returns the
|
|
420
|
-
#
|
|
390
|
+
# Returns the HTTP/2 frame writer registered by {attach_http2} for a
|
|
391
|
+
# connection.
|
|
421
392
|
#
|
|
422
|
-
# @param id [Integer] unique
|
|
423
|
-
# @return [
|
|
393
|
+
# @param id [Integer] unique connection identifier
|
|
394
|
+
# @return [Http2::Writer, nil] the writer, if found
|
|
424
395
|
#
|
|
425
|
-
# @rbs (Integer id) ->
|
|
396
|
+
# @rbs (Integer id) -> Http2::Writer?
|
|
426
397
|
def writer_for(id)
|
|
427
398
|
@id_to_writer[id]
|
|
428
399
|
end
|
|
429
400
|
|
|
430
|
-
# Returns the flow controller
|
|
431
|
-
#
|
|
401
|
+
# Returns the HTTP/2 flow controller registered by {attach_http2} for a
|
|
402
|
+
# connection.
|
|
432
403
|
#
|
|
433
|
-
# @param id [Integer] unique
|
|
434
|
-
# @return [
|
|
404
|
+
# @param id [Integer] unique connection identifier
|
|
405
|
+
# @return [Http2::FlowControl, nil] the flow controller, if found
|
|
435
406
|
#
|
|
436
|
-
# @rbs (Integer id) ->
|
|
407
|
+
# @rbs (Integer id) -> Http2::FlowControl?
|
|
437
408
|
def flow_control_for(id)
|
|
438
409
|
@id_to_flow_control[id]
|
|
439
410
|
end
|
|
@@ -441,7 +412,7 @@ module Raptor
|
|
|
441
412
|
# Attaches a detached response body to an HTTP/1.x connection.
|
|
442
413
|
#
|
|
443
414
|
# @param socket [TCPSocket] the client socket
|
|
444
|
-
# @param id [Integer] unique
|
|
415
|
+
# @param id [Integer] unique connection identifier
|
|
445
416
|
# @param body [DetachedBody] the response body
|
|
446
417
|
# @param state [Hash] connection state restored once the response finishes
|
|
447
418
|
# @param finished [Proc] called with the close reason
|
|
@@ -458,7 +429,8 @@ module Raptor
|
|
|
458
429
|
body.open
|
|
459
430
|
true
|
|
460
431
|
rescue
|
|
461
|
-
|
|
432
|
+
@io_queue << [:cancel_http1, id]
|
|
433
|
+
@selector.wakeup rescue nil
|
|
462
434
|
raise
|
|
463
435
|
end
|
|
464
436
|
|
|
@@ -466,7 +438,7 @@ module Raptor
|
|
|
466
438
|
# that arrived after graceful draining began.
|
|
467
439
|
#
|
|
468
440
|
# @param id [Integer] unique connection identifier
|
|
469
|
-
# @param stream_id [Integer] HTTP/2 stream identifier
|
|
441
|
+
# @param stream_id [Integer] the HTTP/2 stream identifier
|
|
470
442
|
# @return [Boolean] whether the stream may be dispatched
|
|
471
443
|
#
|
|
472
444
|
# @rbs (Integer id, Integer stream_id) -> bool
|
|
@@ -483,13 +455,15 @@ module Raptor
|
|
|
483
455
|
# Sends GOAWAY on every HTTP/2 connection and fixes the last stream each
|
|
484
456
|
# connection may dispatch while existing application work drains.
|
|
485
457
|
#
|
|
486
|
-
# @
|
|
458
|
+
# @yield for each HTTP/2 connection
|
|
459
|
+
# @yieldparam stream_id [Integer] the last dispatched HTTP/2 stream identifier
|
|
487
460
|
# @yieldreturn [String] serialized GOAWAY frame
|
|
488
461
|
# @return [void]
|
|
489
462
|
#
|
|
490
463
|
# @rbs () { (Integer stream_id) -> String } -> void
|
|
491
464
|
def drain_http2
|
|
492
|
-
|
|
465
|
+
# Connections may attach on other threads while this iterates.
|
|
466
|
+
@id_to_flow_control.keys.each do |id|
|
|
493
467
|
last_stream = @id_to_http2_last_stream[id] || 0
|
|
494
468
|
@id_to_http2_drain_stream[id] = last_stream
|
|
495
469
|
writer = @id_to_writer[id]
|
|
@@ -523,7 +497,7 @@ module Raptor
|
|
|
523
497
|
# Attaches a detached response body to an HTTP/2 stream.
|
|
524
498
|
#
|
|
525
499
|
# @param id [Integer] unique connection identifier
|
|
526
|
-
# @param stream_id [Integer] HTTP/2 stream identifier
|
|
500
|
+
# @param stream_id [Integer] the HTTP/2 stream identifier
|
|
527
501
|
# @param body [DetachedBody] the response body
|
|
528
502
|
# @param finished [Proc] called with the close reason
|
|
529
503
|
# @return [Boolean] whether the body was attached
|
|
@@ -559,7 +533,7 @@ module Raptor
|
|
|
559
533
|
# Cancels a detached response stream.
|
|
560
534
|
#
|
|
561
535
|
# @param id [Integer] unique connection identifier
|
|
562
|
-
# @param stream_id [Integer] HTTP/2 stream identifier
|
|
536
|
+
# @param stream_id [Integer] the HTTP/2 stream identifier
|
|
563
537
|
# @return [void]
|
|
564
538
|
#
|
|
565
539
|
# @rbs (Integer id, Integer stream_id) -> void
|
|
@@ -595,16 +569,16 @@ module Raptor
|
|
|
595
569
|
# Stores an HTTP/2 connection's socket, state, writer, and flow
|
|
596
570
|
# controller in the reactor's per-connection maps.
|
|
597
571
|
#
|
|
598
|
-
# @param id [Integer] unique
|
|
572
|
+
# @param id [Integer] unique connection identifier
|
|
599
573
|
# @param socket [TCPSocket] the connection socket
|
|
600
574
|
# @param state [Hash] initial connection state
|
|
601
|
-
# @param writer [Http2::Writer]
|
|
575
|
+
# @param writer [Http2::Writer] frame writer for the connection
|
|
602
576
|
# @param flow_control [Http2::FlowControl] per-connection outbound flow controller
|
|
603
577
|
# @param ping_frame [String] serialized PING frame for keepalive probes
|
|
604
578
|
# @param ping_payload [String] payload expected in the corresponding acknowledgement
|
|
605
579
|
# @return [void]
|
|
606
580
|
#
|
|
607
|
-
# @rbs (id: Integer, socket: TCPSocket, state: Hash[Symbol, untyped], writer:
|
|
581
|
+
# @rbs (id: Integer, socket: TCPSocket, state: Hash[Symbol, untyped], writer: Http2::Writer, flow_control: Http2::FlowControl, ping_frame: String, ping_payload: String) -> void
|
|
608
582
|
def attach_http2(id:, socket:, state:, writer:, flow_control:, ping_frame:, ping_payload:)
|
|
609
583
|
@id_to_socket[id] = socket
|
|
610
584
|
@socket_to_state[socket] = state
|
|
@@ -634,7 +608,7 @@ module Raptor
|
|
|
634
608
|
|
|
635
609
|
# Registers an attached socket for future reactor-driven reads.
|
|
636
610
|
#
|
|
637
|
-
# @param id [Integer] unique
|
|
611
|
+
# @param id [Integer] unique connection identifier
|
|
638
612
|
# @return [void]
|
|
639
613
|
#
|
|
640
614
|
# @rbs (Integer id) -> void
|
|
@@ -648,27 +622,9 @@ module Raptor
|
|
|
648
622
|
socket.close
|
|
649
623
|
end
|
|
650
624
|
|
|
651
|
-
# Updates connection state for an HTTP/2 connection and re-registers
|
|
652
|
-
# the socket for further reads.
|
|
653
|
-
#
|
|
654
|
-
# @param state [Hash] updated connection state from the ractor pool
|
|
655
|
-
# @return [void]
|
|
656
|
-
#
|
|
657
|
-
# @rbs (Hash[Symbol, untyped] state) -> void
|
|
658
|
-
def update_http2_state(state)
|
|
659
|
-
socket = @id_to_socket[state[:id]]
|
|
660
|
-
return unless socket
|
|
661
|
-
|
|
662
|
-
@socket_to_state[socket] = state
|
|
663
|
-
@queue << socket
|
|
664
|
-
@selector.wakeup
|
|
665
|
-
rescue ClosedQueueError
|
|
666
|
-
socket.close
|
|
667
|
-
end
|
|
668
|
-
|
|
669
625
|
# Closes a connection after writing any frames already queued for it.
|
|
670
626
|
#
|
|
671
|
-
# @param id [Integer] unique
|
|
627
|
+
# @param id [Integer] unique connection identifier
|
|
672
628
|
# @return [void]
|
|
673
629
|
#
|
|
674
630
|
# @rbs (Integer id) -> void
|
|
@@ -741,8 +697,7 @@ module Raptor
|
|
|
741
697
|
type, id, value, body, attached, finished, state = operation
|
|
742
698
|
case type
|
|
743
699
|
when :write
|
|
744
|
-
|
|
745
|
-
queue_output(@id_to_io[id], data)
|
|
700
|
+
queue_output(@id_to_io[id], value)
|
|
746
701
|
connections[id] = true
|
|
747
702
|
when :close
|
|
748
703
|
close_after_writes(id)
|
|
@@ -763,6 +718,8 @@ module Raptor
|
|
|
763
718
|
end
|
|
764
719
|
when :ready_http1
|
|
765
720
|
flush_http1_detached_body(id)
|
|
721
|
+
when :cancel_http1
|
|
722
|
+
remove_http1_detached_body(id, :cancelled)
|
|
766
723
|
when :ready_http2
|
|
767
724
|
mark_http2_detached_body_ready(id, value)
|
|
768
725
|
connections[id] = true
|
|
@@ -791,7 +748,7 @@ module Raptor
|
|
|
791
748
|
# Adds a detached body to an HTTP/1.x connection.
|
|
792
749
|
#
|
|
793
750
|
# @param socket [TCPSocket] the client socket
|
|
794
|
-
# @param id [Integer] unique
|
|
751
|
+
# @param id [Integer] unique connection identifier
|
|
795
752
|
# @param body [DetachedBody] the response body
|
|
796
753
|
# @param state [Hash] connection state restored once the response finishes
|
|
797
754
|
# @param finished [Proc] called with the close reason
|
|
@@ -819,7 +776,7 @@ module Raptor
|
|
|
819
776
|
|
|
820
777
|
# Writes buffered HTTP/1.x body chunks without blocking.
|
|
821
778
|
#
|
|
822
|
-
# @param id [Integer] unique
|
|
779
|
+
# @param id [Integer] unique connection identifier
|
|
823
780
|
# @return [void]
|
|
824
781
|
#
|
|
825
782
|
# @rbs (Integer id) -> void
|
|
@@ -852,7 +809,7 @@ module Raptor
|
|
|
852
809
|
|
|
853
810
|
# Finishes an HTTP/1.x detached response and either reuses or closes its connection.
|
|
854
811
|
#
|
|
855
|
-
# @param id [Integer] unique
|
|
812
|
+
# @param id [Integer] unique connection identifier
|
|
856
813
|
# @param io [Http1IO] connection I/O state
|
|
857
814
|
# @return [void]
|
|
858
815
|
#
|
|
@@ -894,7 +851,7 @@ module Raptor
|
|
|
894
851
|
|
|
895
852
|
# Cancels an HTTP/1.x detached response and closes its connection.
|
|
896
853
|
#
|
|
897
|
-
# @param id [Integer] unique
|
|
854
|
+
# @param id [Integer] unique connection identifier
|
|
898
855
|
# @param reason [Symbol] why the response closed
|
|
899
856
|
# @return [void]
|
|
900
857
|
#
|
|
@@ -913,7 +870,7 @@ module Raptor
|
|
|
913
870
|
# Adds a detached body to an HTTP/2 stream.
|
|
914
871
|
#
|
|
915
872
|
# @param id [Integer] unique connection identifier
|
|
916
|
-
# @param stream_id [Integer] HTTP/2 stream identifier
|
|
873
|
+
# @param stream_id [Integer] the HTTP/2 stream identifier
|
|
917
874
|
# @param body [DetachedBody] the response body
|
|
918
875
|
# @param finished [Proc] called with the close reason
|
|
919
876
|
# @return [void]
|
|
@@ -941,7 +898,7 @@ module Raptor
|
|
|
941
898
|
# Marks an HTTP/2 detached stream eligible for fair scheduling.
|
|
942
899
|
#
|
|
943
900
|
# @param id [Integer] unique connection identifier
|
|
944
|
-
# @param stream_id [Integer] HTTP/2 stream identifier
|
|
901
|
+
# @param stream_id [Integer] the HTTP/2 stream identifier
|
|
945
902
|
# @return [void]
|
|
946
903
|
#
|
|
947
904
|
# @rbs (Integer id, Integer stream_id) -> void
|
|
@@ -1017,7 +974,7 @@ module Raptor
|
|
|
1017
974
|
# Finishes an HTTP/2 detached stream with DATA or trailing HEADERS.
|
|
1018
975
|
#
|
|
1019
976
|
# @param id [Integer] unique connection identifier
|
|
1020
|
-
# @param stream_id [Integer] HTTP/2 stream identifier
|
|
977
|
+
# @param stream_id [Integer] the HTTP/2 stream identifier
|
|
1021
978
|
# @param body [DetachedBody] the response body
|
|
1022
979
|
# @return [void]
|
|
1023
980
|
#
|
|
@@ -1039,7 +996,7 @@ module Raptor
|
|
|
1039
996
|
# Removes an HTTP/2 detached stream and schedules its close callback.
|
|
1040
997
|
#
|
|
1041
998
|
# @param id [Integer] unique connection identifier
|
|
1042
|
-
# @param stream_id [Integer] HTTP/2 stream identifier
|
|
999
|
+
# @param stream_id [Integer] the HTTP/2 stream identifier
|
|
1043
1000
|
# @param reason [Symbol] why the stream closed
|
|
1044
1001
|
# @return [void]
|
|
1045
1002
|
#
|
|
@@ -1087,7 +1044,7 @@ module Raptor
|
|
|
1087
1044
|
|
|
1088
1045
|
# Closes a connection once its queued frames are written.
|
|
1089
1046
|
#
|
|
1090
|
-
# @param id [Integer] unique
|
|
1047
|
+
# @param id [Integer] unique connection identifier
|
|
1091
1048
|
# @return [void]
|
|
1092
1049
|
#
|
|
1093
1050
|
# @rbs (Integer id) -> void
|
|
@@ -1104,7 +1061,7 @@ module Raptor
|
|
|
1104
1061
|
|
|
1105
1062
|
# Immediately closes a connection and drops its reactor state.
|
|
1106
1063
|
#
|
|
1107
|
-
# @param id [Integer] unique
|
|
1064
|
+
# @param id [Integer] unique connection identifier
|
|
1108
1065
|
# @return [void]
|
|
1109
1066
|
#
|
|
1110
1067
|
# @rbs (Integer id) -> void
|
|
@@ -1113,9 +1070,9 @@ module Raptor
|
|
|
1113
1070
|
cleanup(socket) if socket
|
|
1114
1071
|
end
|
|
1115
1072
|
|
|
1116
|
-
#
|
|
1073
|
+
# Appends bytes to one connection's pending output.
|
|
1117
1074
|
#
|
|
1118
|
-
# @param io [ConnectionIO] connection I/O state
|
|
1075
|
+
# @param io [ConnectionIO, nil] connection I/O state
|
|
1119
1076
|
# @param data [String] serialized response bytes
|
|
1120
1077
|
# @return [void]
|
|
1121
1078
|
#
|
|
@@ -1133,7 +1090,7 @@ module Raptor
|
|
|
1133
1090
|
# Drains one connection's queued response bytes without blocking.
|
|
1134
1091
|
#
|
|
1135
1092
|
# @param id [Integer] unique connection identifier
|
|
1136
|
-
# @param io [ConnectionIO] connection I/O state
|
|
1093
|
+
# @param io [ConnectionIO, nil] connection I/O state
|
|
1137
1094
|
# @return [void]
|
|
1138
1095
|
#
|
|
1139
1096
|
# @rbs (Integer id, ConnectionIO? io) -> void
|
|
@@ -1372,6 +1329,7 @@ module Raptor
|
|
|
1372
1329
|
flush_output(id, io)
|
|
1373
1330
|
return unless @id_to_socket.key?(id)
|
|
1374
1331
|
return if io.wait == :read
|
|
1332
|
+
|
|
1375
1333
|
flush_http2_detached_bodies(id) unless io.detached.empty?
|
|
1376
1334
|
end
|
|
1377
1335
|
|
|
@@ -1379,15 +1337,15 @@ module Raptor
|
|
|
1379
1337
|
|
|
1380
1338
|
io.reading = false
|
|
1381
1339
|
update_monitor(id, io)
|
|
1382
|
-
|
|
1383
|
-
@timeouts.delete!(
|
|
1340
|
+
client = @id_to_timeout.delete(id)
|
|
1341
|
+
@timeouts.delete!(client) if client
|
|
1384
1342
|
read_and_queue_for_parse(socket, state)
|
|
1385
1343
|
end
|
|
1386
1344
|
|
|
1387
1345
|
# Handles readiness for an HTTP/1.x detached response.
|
|
1388
1346
|
#
|
|
1389
1347
|
# @param monitor [NIO::Monitor] ready selector monitor
|
|
1390
|
-
# @param id [Integer] unique
|
|
1348
|
+
# @param id [Integer] unique connection identifier
|
|
1391
1349
|
# @return [void]
|
|
1392
1350
|
#
|
|
1393
1351
|
# @rbs (NIO::Monitor monitor, Integer id) -> void
|
|
@@ -1416,7 +1374,8 @@ module Raptor
|
|
|
1416
1374
|
remove_connection(id)
|
|
1417
1375
|
end
|
|
1418
1376
|
|
|
1419
|
-
#
|
|
1377
|
+
# Deregisters a readable socket and resumes its idle keep-alive
|
|
1378
|
+
# connection or queues its bytes for parsing.
|
|
1420
1379
|
#
|
|
1421
1380
|
# @param socket [TCPSocket] the socket that became ready
|
|
1422
1381
|
# @return [void]
|
|
@@ -1425,9 +1384,40 @@ module Raptor
|
|
|
1425
1384
|
def wakeup!(socket)
|
|
1426
1385
|
@selector.deregister(socket)
|
|
1427
1386
|
state = @socket_to_state[socket]
|
|
1428
|
-
|
|
1429
|
-
@timeouts.delete!(
|
|
1430
|
-
|
|
1387
|
+
client = @id_to_timeout.delete(state[:id])
|
|
1388
|
+
@timeouts.delete!(client) if client
|
|
1389
|
+
|
|
1390
|
+
if state[:persisted] && !state.key?(:buffer)
|
|
1391
|
+
resume_keepalive(socket, state)
|
|
1392
|
+
else
|
|
1393
|
+
read_and_queue_for_parse(socket, state)
|
|
1394
|
+
end
|
|
1395
|
+
end
|
|
1396
|
+
|
|
1397
|
+
# Resumes a readable keep-alive connection on an application thread,
|
|
1398
|
+
# avoiding a Ractor round trip for complete requests.
|
|
1399
|
+
#
|
|
1400
|
+
# @param socket [TCPSocket] the readable client socket
|
|
1401
|
+
# @param state [Hash] current connection state
|
|
1402
|
+
# @return [void]
|
|
1403
|
+
#
|
|
1404
|
+
# @rbs (TCPSocket socket, Hash[Symbol, untyped] state) -> void
|
|
1405
|
+
def resume_keepalive(socket, state)
|
|
1406
|
+
remove(state[:id])
|
|
1407
|
+
@thread_pool << proc do
|
|
1408
|
+
@http1.eager_keepalive(
|
|
1409
|
+
socket,
|
|
1410
|
+
state[:id],
|
|
1411
|
+
self,
|
|
1412
|
+
@thread_pool,
|
|
1413
|
+
state[:request_count],
|
|
1414
|
+
state[:remote_addr],
|
|
1415
|
+
state[:url_scheme],
|
|
1416
|
+
resumed: true
|
|
1417
|
+
)
|
|
1418
|
+
end
|
|
1419
|
+
rescue AtomicThreadPool::EnqueuedWorkAfterShutdownError
|
|
1420
|
+
socket.close rescue nil
|
|
1431
1421
|
end
|
|
1432
1422
|
|
|
1433
1423
|
# Reads data from a socket and either queues it for parsing or
|
|
@@ -1435,9 +1425,9 @@ module Raptor
|
|
|
1435
1425
|
#
|
|
1436
1426
|
# @param socket [TCPSocket] the socket to read from and queue
|
|
1437
1427
|
# @param state [Hash] current connection state
|
|
1438
|
-
# @return [
|
|
1428
|
+
# @return [void]
|
|
1439
1429
|
#
|
|
1440
|
-
# @rbs (TCPSocket socket, Hash[Symbol, untyped] state) ->
|
|
1430
|
+
# @rbs (TCPSocket socket, Hash[Symbol, untyped] state) -> void
|
|
1441
1431
|
def read_and_queue_for_parse(socket, state)
|
|
1442
1432
|
data = begin
|
|
1443
1433
|
socket.read_nonblock(CHUNK_SIZE)
|
|
@@ -1496,20 +1486,20 @@ module Raptor
|
|
|
1496
1486
|
socket.close rescue nil
|
|
1497
1487
|
end
|
|
1498
1488
|
|
|
1499
|
-
# Returns
|
|
1489
|
+
# Returns whether the request has been fully parsed.
|
|
1500
1490
|
#
|
|
1501
1491
|
# @param state [Hash] connection state
|
|
1502
|
-
# @return [Boolean]
|
|
1492
|
+
# @return [Boolean]
|
|
1503
1493
|
#
|
|
1504
1494
|
# @rbs (Hash[Symbol, untyped] state) -> bool
|
|
1505
1495
|
def complete?(state)
|
|
1506
1496
|
state[:complete]
|
|
1507
1497
|
end
|
|
1508
1498
|
|
|
1509
|
-
#
|
|
1499
|
+
# Returns whether any data has been received for this connection.
|
|
1510
1500
|
#
|
|
1511
1501
|
# @param state [Hash] connection state
|
|
1512
|
-
# @return [Boolean]
|
|
1502
|
+
# @return [Boolean]
|
|
1513
1503
|
#
|
|
1514
1504
|
# @rbs (Hash[Symbol, untyped] state) -> bool
|
|
1515
1505
|
def first_data_received?(state)
|