raptor 0.24.0 → 0.25.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 +4 -0
- data/README.md +56 -56
- data/docs/raptor-vs-puma.md +4 -2
- data/docs/talk.md +1 -1
- data/lib/raptor/reactor.rb +102 -72
- data/lib/raptor/version.rb +1 -1
- data/lib/raptor.rb +1 -1
- data/sig/generated/raptor/reactor.rbs +31 -16
- data/sig/generated/raptor.rbs +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 59fe5e87d01266b5c1c95e08e24339fc1bae9748c9ed814d4694903a2bbce8c5
|
|
4
|
+
data.tar.gz: 53cb18d26ad63f298a7a94496c536b561de3c7be29113df8ee77736d20c9019e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e8a0997c88a5f7962cf9ae1d1a7e5ceb18830a321fc722cd88e87e848e998a68f0d2aa6bb091b5f6c0a7a074666a580150038d8ea52820f0518ff9f14e745ca7
|
|
7
|
+
data.tar.gz: 67178c0c92dca4d419f2127185c0df981f67e9e5e561b05d2f0c67fdb953db5db1d5866ae35d2b2a48b8a2bfe02439d7a41305da7fa691c04d3057edfbce73a0
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [0.25.0] - 2026-11-08
|
|
4
|
+
|
|
5
|
+
- Replace nio4r with io-event for reactor I/O readiness without changing application threading
|
|
6
|
+
|
|
3
7
|
## [0.24.0] - 2026-11-08
|
|
4
8
|
|
|
5
9
|
- Honour `connection.max_body_size` for HTTP/2 request bodies without closing other streams
|
data/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Raptor
|
|
2
2
|
|
|
3
3
|
Raptor is a high-performance, preloading, pre-forking, multi-threaded Ruby 4+ web server implementing Rack 3.2+, using
|
|
4
|
-
|
|
4
|
+
io-event for non-blocking I/O and Ractors for parallel HTTP/1.1 and HTTP/2 parsing via native C extensions, which also
|
|
5
5
|
implement HPACK compression.
|
|
6
6
|
|
|
7
7
|
> [!NOTE]
|
|
@@ -250,7 +250,7 @@ Set `control_url` to a Unix socket URL such as `unix:///tmp/raptor-control.sock`
|
|
|
250
250
|
|
|
251
251
|
## (Micro) Benchmarks
|
|
252
252
|
|
|
253
|
-
Raptor 0.
|
|
253
|
+
Raptor 0.25.0 vs Puma 8.0.2 vs Falcon 0.57.0. Each case has 3 fresh-process samples, interleaved in seeded shuffled
|
|
254
254
|
rounds. Each sample warms up for 3s and measures for 15s. Metrics are independent medians. ± is (max − min) / 2 /
|
|
255
255
|
median, not a confidence interval. Failure counts below each table sum all samples, so a failed run cannot disappear in
|
|
256
256
|
a median. Throughput counts successful ordinary requests only.
|
|
@@ -278,92 +278,92 @@ accounting for shared pages instead of counting them fully in every worker.
|
|
|
278
278
|
|
|
279
279
|
| Server | Mode | Raptor baseline | req/s | vs Raptor req/s | p95 ms | vs Raptor p95 | CPU ms/req | PSS MiB |
|
|
280
280
|
| ------ | -------------- | --------------- | ------------ | --------------- | ------ | ------------- | ---------- | ------- |
|
|
281
|
-
| Raptor | Fixed (3) | - | 3.
|
|
282
|
-
| Raptor | Scaling (3–16) | - | 8.
|
|
283
|
-
| Puma | Fixed (3) | Fixed (3) | 1.
|
|
284
|
-
| Puma | Scaling (3–16) | Scaling (3–16) | 8.
|
|
285
|
-
| Falcon | Fibers | Fixed (3) | 10.
|
|
286
|
-
| Falcon | Fibers | Scaling (3–16) | 10.
|
|
281
|
+
| Raptor | Fixed (3) | - | 3.41k ±0.9% | - | 44.85 | - | 2.438 | 363.9 |
|
|
282
|
+
| Raptor | Scaling (3–16) | - | 8.12k ±0.8% | - | 22.30 | - | 0.495 | 332.2 |
|
|
283
|
+
| Puma | Fixed (3) | Fixed (3) | 1.53k ±1.3% | 55.0% lower | 118.30 | 163.8% higher | 0.950 | 289.8 |
|
|
284
|
+
| Puma | Scaling (3–16) | Scaling (3–16) | 8.22k ±0.3% | 1.3% higher | 22.02 | 1.3% lower | 0.484 | 337.6 |
|
|
285
|
+
| Falcon | Fibers | Fixed (3) | 10.87k ±0.4% | 218.7% higher | 15.63 | 65.1% lower | 0.468 | 437.3 |
|
|
286
|
+
| Falcon | Fibers | Scaling (3–16) | 10.87k ±0.4% | 34.0% higher | 15.63 | 29.9% lower | 0.468 | 437.3 |
|
|
287
287
|
|
|
288
288
|
### IO over HTTP/1.1 keep-alive
|
|
289
289
|
|
|
290
290
|
| Server | Mode | Raptor baseline | req/s | vs Raptor req/s | p95 ms | vs Raptor p95 | CPU ms/req | PSS MiB |
|
|
291
291
|
| ------ | -------------- | --------------- | ----------- | --------------- | ------ | ------------- | ---------- | ------- |
|
|
292
|
-
| Raptor | Fixed (3) | - | 3.
|
|
293
|
-
| Raptor | Scaling (3–16) | - | 7.
|
|
294
|
-
| Raptor | Fixed (16) | - | 7.
|
|
295
|
-
| Puma | Fixed (3) | Fixed (3) | 1.
|
|
296
|
-
| Puma | Scaling (3–16) | Scaling (3–16) | 7.
|
|
297
|
-
| Puma | Fixed (16) | Fixed (16) | 7.
|
|
298
|
-
| Falcon | Fibers | Fixed (3) | 7.
|
|
299
|
-
| Falcon | Fibers | Scaling (3–16) | 7.
|
|
300
|
-
| Falcon | Fibers | Fixed (16) | 7.
|
|
292
|
+
| Raptor | Fixed (3) | - | 3.40k ±3.1% | - | 38.77 | - | 2.440 | 369.9 |
|
|
293
|
+
| Raptor | Scaling (3–16) | - | 7.44k ±0.4% | - | 24.43 | - | 0.494 | 356.2 |
|
|
294
|
+
| Raptor | Fixed (16) | - | 7.55k ±2.0% | - | 24.11 | - | 0.475 | 358.0 |
|
|
295
|
+
| Puma | Fixed (3) | Fixed (3) | 1.50k ±0.8% | 56.0% lower | 104.07 | 168.5% higher | 1.038 | 299.3 |
|
|
296
|
+
| Puma | Scaling (3–16) | Scaling (3–16) | 7.44k ±0.3% | 0.1% higher | 24.44 | 0.1% higher | 0.441 | 341.3 |
|
|
297
|
+
| Puma | Fixed (16) | Fixed (16) | 7.59k ±1.2% | 0.5% higher | 23.94 | 0.7% lower | 0.442 | 345.2 |
|
|
298
|
+
| Falcon | Fibers | Fixed (3) | 7.58k ±4.3% | 123.1% higher | 23.89 | 38.4% lower | 0.408 | 365.3 |
|
|
299
|
+
| Falcon | Fibers | Scaling (3–16) | 7.58k ±4.3% | 1.9% higher | 23.89 | 2.2% lower | 0.408 | 365.3 |
|
|
300
|
+
| Falcon | Fibers | Fixed (16) | 7.58k ±4.3% | 0.4% higher | 23.89 | 0.9% lower | 0.408 | 365.3 |
|
|
301
301
|
|
|
302
302
|
### IO over HTTP/2
|
|
303
303
|
|
|
304
|
-
| Server | Mode | Raptor baseline | req/s
|
|
305
|
-
| ------ | -------------- | --------------- |
|
|
306
|
-
| Raptor | Fixed (3) | - | 1.60k ±
|
|
307
|
-
| Raptor | Scaling (3–16) | - |
|
|
308
|
-
| Falcon | Fibers | Fixed (3) | 7.
|
|
309
|
-
| Falcon | Fibers | Scaling (3–16) | 7.
|
|
304
|
+
| Server | Mode | Raptor baseline | req/s | vs Raptor req/s | p95 ms | vs Raptor p95 | CPU ms/req | PSS MiB |
|
|
305
|
+
| ------ | -------------- | --------------- | ------------ | --------------- | ------ | ------------- | ---------- | ------- |
|
|
306
|
+
| Raptor | Fixed (3) | - | 1.60k ±0.3% | - | 130.95 | - | 0.937 | 474.6 |
|
|
307
|
+
| Raptor | Scaling (3–16) | - | 8.03k ±5.7% | - | 23.92 | - | 0.573 | 905.4 |
|
|
308
|
+
| Falcon | Fibers | Fixed (3) | 7.55k ±10.7% | 370.7% higher | 25.90 | 80.2% lower | 0.462 | 497.3 |
|
|
309
|
+
| Falcon | Fibers | Scaling (3–16) | 7.55k ±10.7% | 5.9% lower | 25.90 | 8.3% higher | 0.462 | 497.3 |
|
|
310
310
|
|
|
311
311
|
### CPU over HTTP/1.1
|
|
312
312
|
|
|
313
313
|
| Server | Mode | Raptor baseline | req/s | vs Raptor req/s | p95 ms | vs Raptor p95 | CPU ms/req | PSS MiB |
|
|
314
314
|
| ------ | -------------- | --------------- | ----------- | --------------- | ------ | ------------- | ---------- | ------- |
|
|
315
|
-
| Raptor | Fixed (3) | - | 3.
|
|
316
|
-
| Raptor | Scaling (3–16) | - | 3.
|
|
317
|
-
| Puma | Fixed (3) | Fixed (3) |
|
|
318
|
-
| Puma | Scaling (3–16) | Scaling (3–16) |
|
|
319
|
-
| Falcon | Fibers | Fixed (3) | 3.
|
|
320
|
-
| Falcon | Fibers | Scaling (3–16) | 3.
|
|
315
|
+
| Raptor | Fixed (3) | - | 3.38k ±1.4% | - | 68.70 | - | 2.546 | 506.9 |
|
|
316
|
+
| Raptor | Scaling (3–16) | - | 3.37k ±2.4% | - | 63.69 | - | 2.482 | 532.6 |
|
|
317
|
+
| Puma | Fixed (3) | Fixed (3) | 3.17k ±1.2% | 6.2% lower | 56.91 | 17.2% lower | 2.521 | 451.2 |
|
|
318
|
+
| Puma | Scaling (3–16) | Scaling (3–16) | 3.20k ±3.9% | 5.1% lower | 50.38 | 20.9% lower | 2.236 | 460.7 |
|
|
319
|
+
| Falcon | Fibers | Fixed (3) | 3.40k ±1.0% | 0.7% higher | 47.88 | 30.3% lower | 2.533 | 428.3 |
|
|
320
|
+
| Falcon | Fibers | Scaling (3–16) | 3.40k ±1.0% | 0.9% higher | 47.88 | 24.8% lower | 2.533 | 428.3 |
|
|
321
321
|
|
|
322
322
|
### CPU over HTTP/1.1 keep-alive
|
|
323
323
|
|
|
324
324
|
| Server | Mode | Raptor baseline | req/s | vs Raptor req/s | p95 ms | vs Raptor p95 | CPU ms/req | PSS MiB |
|
|
325
325
|
| ------ | -------------- | --------------- | ----------- | --------------- | ------ | ------------- | ---------- | ------- |
|
|
326
|
-
| Raptor | Fixed (3) | - |
|
|
327
|
-
| Raptor | Scaling (3–16) | - | 2.
|
|
328
|
-
| Puma | Fixed (3) | Fixed (3) | 3.
|
|
329
|
-
| Puma | Scaling (3–16) | Scaling (3–16) | 2.
|
|
330
|
-
| Falcon | Fibers | Fixed (3) | 3.
|
|
331
|
-
| Falcon | Fibers | Scaling (3–16) | 3.
|
|
326
|
+
| Raptor | Fixed (3) | - | 3.09k ±3.7% | - | 59.42 | - | 2.732 | 503.7 |
|
|
327
|
+
| Raptor | Scaling (3–16) | - | 2.93k ±2.0% | - | 50.46 | - | 2.645 | 518.6 |
|
|
328
|
+
| Puma | Fixed (3) | Fixed (3) | 3.41k ±6.7% | 10.7% higher | 57.91 | 2.5% lower | 2.423 | 406.4 |
|
|
329
|
+
| Puma | Scaling (3–16) | Scaling (3–16) | 2.79k ±1.6% | 4.9% lower | 66.33 | 31.5% higher | 2.291 | 497.1 |
|
|
330
|
+
| Falcon | Fibers | Fixed (3) | 3.01k ±6.2% | 2.5% lower | 73.18 | 23.1% higher | 2.920 | 563.1 |
|
|
331
|
+
| Falcon | Fibers | Scaling (3–16) | 3.01k ±6.2% | 2.6% higher | 73.18 | 45.0% higher | 2.920 | 563.1 |
|
|
332
332
|
|
|
333
333
|
### CPU over HTTP/2
|
|
334
334
|
|
|
335
335
|
| Server | Mode | Raptor baseline | req/s | vs Raptor req/s | p95 ms | vs Raptor p95 | CPU ms/req | PSS MiB |
|
|
336
336
|
| ------ | -------------- | --------------- | ------------ | --------------- | ------ | ------------- | ---------- | ------- |
|
|
337
|
-
| Raptor | Fixed (3) | - | 3.
|
|
338
|
-
| Raptor | Scaling (3–16) | - | 3.
|
|
339
|
-
| Falcon | Fibers | Fixed (3) |
|
|
340
|
-
| Falcon | Fibers | Scaling (3–16) |
|
|
337
|
+
| Raptor | Fixed (3) | - | 3.20k ±2.9% | - | 72.40 | - | 2.401 | 621.4 |
|
|
338
|
+
| Raptor | Scaling (3–16) | - | 3.11k ±1.4% | - | 75.04 | - | 2.403 | 597.8 |
|
|
339
|
+
| Falcon | Fibers | Fixed (3) | 2.45k ±20.8% | 23.4% lower | 147.43 | 103.6% higher | 2.616 | 567.1 |
|
|
340
|
+
| Falcon | Fibers | Scaling (3–16) | 2.45k ±20.8% | 21.2% lower | 147.43 | 96.5% higher | 2.616 | 567.1 |
|
|
341
341
|
|
|
342
342
|
### 64 KiB body over HTTP/1.1 keep-alive
|
|
343
343
|
|
|
344
|
-
| Server | Mode | Raptor baseline | req/s
|
|
345
|
-
| ------ | -------------- | --------------- |
|
|
346
|
-
| Raptor | Scaling (3–16) | - | 96.
|
|
347
|
-
| Puma | Scaling (3–16) | Scaling (3–16) |
|
|
348
|
-
| Falcon | Fibers | Scaling (3–16) |
|
|
344
|
+
| Server | Mode | Raptor baseline | req/s | vs Raptor req/s | p95 ms | vs Raptor p95 | CPU ms/req | PSS MiB |
|
|
345
|
+
| ------ | -------------- | --------------- | ------------- | --------------- | ------ | ------------- | ---------- | ------- |
|
|
346
|
+
| Raptor | Scaling (3–16) | - | 96.95k ±0.5% | - | 3.59 | - | 0.051 | 554.2 |
|
|
347
|
+
| Puma | Scaling (3–16) | Scaling (3–16) | 90.31k ±0.5% | 6.8% lower | 3.56 | 0.9% lower | 0.052 | 1447.0 |
|
|
348
|
+
| Falcon | Fibers | Scaling (3–16) | 106.79k ±0.8% | 10.2% higher | 3.70 | 3.0% higher | 0.050 | 642.1 |
|
|
349
349
|
|
|
350
350
|
### IO + SSE (native) over HTTP/1.1 keep-alive
|
|
351
351
|
|
|
352
|
-
| Server | Mode | Raptor baseline | req/s
|
|
353
|
-
| ------------- | -------------- | --------------- |
|
|
354
|
-
| Raptor | Fixed (3) | - | 3.
|
|
355
|
-
| Raptor | Scaling (3–16) | - | 7.
|
|
356
|
-
| Puma | Fixed (3) | Fixed (3) | 0.
|
|
357
|
-
| Puma | Scaling (3–16) | Scaling (3–16) | 7.
|
|
358
|
-
| Falcon | Fibers | Fixed (3) | 7.
|
|
359
|
-
| Falcon | Fibers | Scaling (3–16) | 7.
|
|
360
|
-
| Raptor (enum) | Fixed (3) | - | 0.
|
|
352
|
+
| Server | Mode | Raptor baseline | req/s | vs Raptor req/s | p95 ms | vs Raptor p95 | CPU ms/req | PSS MiB |
|
|
353
|
+
| ------------- | -------------- | --------------- | ----------- | --------------- | ------ | ------------- | ---------- | ------- |
|
|
354
|
+
| Raptor | Fixed (3) | - | 3.43k ±8.5% | - | 35.14 | - | 2.448 | 378.5 |
|
|
355
|
+
| Raptor | Scaling (3–16) | - | 7.58k ±1.5% | - | 23.79 | - | 0.485 | 373.3 |
|
|
356
|
+
| Puma | Fixed (3) | Fixed (3) | 0.34k ±6.3% | 90.0% lower | 327.51 | 832.1% higher | 1.744 | 281.0 |
|
|
357
|
+
| Puma | Scaling (3–16) | Scaling (3–16) | 7.38k ±1.4% | 2.6% lower | 24.55 | 3.2% higher | 0.443 | 339.9 |
|
|
358
|
+
| Falcon | Fibers | Fixed (3) | 7.51k ±4.0% | 118.8% higher | 24.31 | 30.8% lower | 0.413 | 371.0 |
|
|
359
|
+
| Falcon | Fibers | Scaling (3–16) | 7.51k ±4.0% | 1.0% lower | 24.31 | 2.2% higher | 0.413 | 371.0 |
|
|
360
|
+
| Raptor (enum) | Fixed (3) | - | 0.89k ±3.3% | - | 58.38 | - | 8.363 | 356.0 |
|
|
361
361
|
|
|
362
|
-
Puma, Fixed (3) had
|
|
362
|
+
Puma, Fixed (3) had 34 timeouts, 1 stalled stream across all samples.
|
|
363
363
|
|
|
364
|
-
Raptor (enum), Fixed (3) had
|
|
364
|
+
Raptor (enum), Fixed (3) had 24 timeouts across all samples.
|
|
365
365
|
|
|
366
|
-
> ruby 4.1.0dev (2026-
|
|
366
|
+
> ruby 4.1.0dev (2026-11-07T16:07:23Z HEAD e67e4a6960) +YJIT +PRISM [aarch64-linux]
|
|
367
367
|
> 10 workers, 120 HTTP/1.1 client connections, 40 HTTP/2 connections × 3 streams.
|
|
368
368
|
|
|
369
369
|
Run [bin/benchmark](bin/benchmark) to reproduce.
|
data/docs/raptor-vs-puma.md
CHANGED
|
@@ -16,7 +16,7 @@ This guide compares their architecture and relates it to the [current README ben
|
|
|
16
16
|
| Protocol processing | App threads and reactor share the worker's GVL | Eager parsing inline, separate protocol Ractors on the pipeline path |
|
|
17
17
|
| Pool coordination | Mutex and condition variables | Lock-free work queue with idle-thread parking |
|
|
18
18
|
| Pool growth | Adds threads when queued work exceeds waiting capacity | Adds threads when queued work and blocking time justify growth |
|
|
19
|
-
| Idle and partial connections | `nio4r` reactor | `
|
|
19
|
+
| Idle and partial connections | `nio4r` reactor | `io-event` reactor |
|
|
20
20
|
| Cluster dispatch | Shared listeners with load-sensitive accept delay | Shared listeners, plus load-aware BPF dispatch on supported Linux TCP bindings |
|
|
21
21
|
| HTTP/2 | Not implemented | Native parsing, HPACK and stream flow control |
|
|
22
22
|
| Worker monitoring | Pipe messages | Shared-memory stats |
|
|
@@ -129,7 +129,7 @@ flowchart TB
|
|
|
129
129
|
subgraph Worker["Raptor worker process, one of N"]
|
|
130
130
|
SRV["Server thread<br/>IO.select + accept_nonblock<br/>polls for pool capacity"]
|
|
131
131
|
|
|
132
|
-
RCT["Reactor thread<br/>
|
|
132
|
+
RCT["Reactor thread<br/>io-event selector<br/>read_nonblock 64KB<br/>Red-Black-Tree timeouts"]
|
|
133
133
|
|
|
134
134
|
subgraph RP1["HTTP/1.1 RactorPool"]
|
|
135
135
|
RW1["Pipeline Ractor 1<br/>HTTP/1.x parser<br/>chunked decode"]
|
|
@@ -211,6 +211,8 @@ Puma's cluster accept delay backs off according to worker load. On supported Lin
|
|
|
211
211
|
|
|
212
212
|
Both reactors keep idle and partial connections off application threads. Puma tracks deadlines in a sorted array. Raptor uses a red-black tree for logarithmic insertion and removal of individual deadlines. Updating a connection's deadline does not require scanning the other connections.
|
|
213
213
|
|
|
214
|
+
Raptor uses `io-event` readiness fibers only on its reactor thread. It does not install a Fiber scheduler or change how the application runs.
|
|
215
|
+
|
|
214
216
|
### Responses and streaming
|
|
215
217
|
|
|
216
218
|
Ordinary HTTP/1.1 response writing runs on app threads in both servers. Raptor can gather headers and array-body buffers with `writev` and reuse per-thread response buffers. Puma uses its own buffered writes and Linux TCP corking. Both support file bodies and enumerable streaming bodies.
|
data/docs/talk.md
CHANGED
|
@@ -640,7 +640,7 @@ with no hard maximum. You don't have to choose one fixed thread count.</big>
|
|
|
640
640
|
|
|
641
641
|
Slow clients, half-sent requests, and idle keep-alive connections aren't ready to be read yet. The reactor watches all of them at once.
|
|
642
642
|
|
|
643
|
-
<big>
|
|
643
|
+
<big>It uses [`io-event`](https://github.com/socketry/io-event), backed by `epoll` on Linux
|
|
644
644
|
and `kqueue` on macOS.</big>
|
|
645
645
|
|
|
646
646
|
<big>The HTTP/1.1 defaults are 30 seconds for the first bytes,
|
data/lib/raptor/reactor.rb
CHANGED
|
@@ -9,7 +9,7 @@ require "atomic-ruby/atomic_boolean"
|
|
|
9
9
|
require "atomic-ruby/atomic_condition_variable"
|
|
10
10
|
require "atomic-ruby/atomic_queue"
|
|
11
11
|
require "atomic-ruby/atomic_thread_pool"
|
|
12
|
-
require "
|
|
12
|
+
require "io/event"
|
|
13
13
|
require "red-black-tree"
|
|
14
14
|
|
|
15
15
|
require_relative "detached_body"
|
|
@@ -76,7 +76,6 @@ module Raptor
|
|
|
76
76
|
attr_accessor :wait #: Symbol?
|
|
77
77
|
attr_accessor :reading #: bool
|
|
78
78
|
attr_accessor :closing #: bool
|
|
79
|
-
attr_accessor :monitor #: NIO::Monitor?
|
|
80
79
|
attr_accessor :timeout #: TimeoutClient?
|
|
81
80
|
attr_reader :output #: Array[String]
|
|
82
81
|
|
|
@@ -91,7 +90,6 @@ module Raptor
|
|
|
91
90
|
@wait = nil
|
|
92
91
|
@reading = false
|
|
93
92
|
@closing = false
|
|
94
|
-
@monitor = nil
|
|
95
93
|
@timeout = nil
|
|
96
94
|
end
|
|
97
95
|
|
|
@@ -182,7 +180,10 @@ module Raptor
|
|
|
182
180
|
# @rbs @persistent_data_timeout: Integer
|
|
183
181
|
# @rbs @http2_keepalive_interval: Integer
|
|
184
182
|
# @rbs @http2_keepalive_timeout: Integer
|
|
185
|
-
# @rbs @selector:
|
|
183
|
+
# @rbs @selector: untyped
|
|
184
|
+
# @rbs @wakeup: Fiber?
|
|
185
|
+
# @rbs @waiters: Hash[TCPSocket, [Fiber, Integer]]
|
|
186
|
+
# @rbs @ready: Array[[TCPSocket, Integer]]
|
|
186
187
|
# @rbs @queue: Queue[TCPSocket]
|
|
187
188
|
# @rbs @io_queue: AtomicQueue
|
|
188
189
|
# @rbs @io_applied: AtomicConditionVariable
|
|
@@ -231,7 +232,10 @@ module Raptor
|
|
|
231
232
|
@http2_keepalive_interval = http2_options[:keepalive_interval]
|
|
232
233
|
@http2_keepalive_timeout = http2_options[:keepalive_timeout]
|
|
233
234
|
|
|
234
|
-
@selector =
|
|
235
|
+
@selector = nil
|
|
236
|
+
@wakeup = nil
|
|
237
|
+
@waiters = {}
|
|
238
|
+
@ready = []
|
|
235
239
|
@queue = Queue.new
|
|
236
240
|
@io_queue = AtomicQueue.new
|
|
237
241
|
@io_applied = AtomicConditionVariable.new
|
|
@@ -262,13 +266,19 @@ module Raptor
|
|
|
262
266
|
Thread.new do
|
|
263
267
|
Thread.current.name = "Reactor"
|
|
264
268
|
@thread = Thread.current
|
|
269
|
+
selector = IO::Event::Selector.new(Fiber.current)
|
|
270
|
+
@wakeup = Fiber.new { loop { selector.transfer } }
|
|
271
|
+
@selector = selector
|
|
265
272
|
|
|
266
273
|
until stopped?
|
|
267
274
|
begin
|
|
268
275
|
now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
269
276
|
timeout = @timeouts.min&.timeout(now)
|
|
270
|
-
@
|
|
271
|
-
|
|
277
|
+
timeout = 0 unless @ready.empty? && @queue.empty? && @io_queue.empty?
|
|
278
|
+
@selector.select(timeout)
|
|
279
|
+
until @ready.empty?
|
|
280
|
+
socket, events = @ready.shift
|
|
281
|
+
handle_ready(socket, events)
|
|
272
282
|
end
|
|
273
283
|
|
|
274
284
|
now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
@@ -283,6 +293,8 @@ module Raptor
|
|
|
283
293
|
end
|
|
284
294
|
end
|
|
285
295
|
|
|
296
|
+
@waiters.keys.each { |socket| deregister(socket) }
|
|
297
|
+
@ready.clear
|
|
286
298
|
@id_to_flow_control.each_value(&:close)
|
|
287
299
|
@id_to_socket.each_value { |socket| socket.close rescue nil }
|
|
288
300
|
@id_to_socket.clear
|
|
@@ -330,7 +342,7 @@ module Raptor
|
|
|
330
342
|
|
|
331
343
|
@socket_to_state[socket] = state
|
|
332
344
|
@queue << socket
|
|
333
|
-
|
|
345
|
+
wakeup
|
|
334
346
|
rescue ClosedQueueError
|
|
335
347
|
socket.close
|
|
336
348
|
end
|
|
@@ -372,7 +384,7 @@ module Raptor
|
|
|
372
384
|
@id_to_socket[id] = socket
|
|
373
385
|
@socket_to_state[socket] = state
|
|
374
386
|
@queue << socket
|
|
375
|
-
|
|
387
|
+
wakeup
|
|
376
388
|
rescue ClosedQueueError
|
|
377
389
|
socket.close
|
|
378
390
|
end
|
|
@@ -422,7 +434,7 @@ module Raptor
|
|
|
422
434
|
def attach_http1_body(socket, id, body, state, finished)
|
|
423
435
|
attached = AtomicBoolean.new(false)
|
|
424
436
|
@io_queue << [:attach_http1, id, socket, body, attached, finished, state]
|
|
425
|
-
|
|
437
|
+
wakeup rescue nil
|
|
426
438
|
@io_applied.wait { attached.true? }
|
|
427
439
|
return false if body.closed?
|
|
428
440
|
|
|
@@ -430,7 +442,7 @@ module Raptor
|
|
|
430
442
|
true
|
|
431
443
|
rescue
|
|
432
444
|
@io_queue << [:cancel_http1, id]
|
|
433
|
-
|
|
445
|
+
wakeup rescue nil
|
|
434
446
|
raise
|
|
435
447
|
end
|
|
436
448
|
|
|
@@ -490,7 +502,7 @@ module Raptor
|
|
|
490
502
|
flush_output(id, io) if io && !io.wait
|
|
491
503
|
else
|
|
492
504
|
@io_queue << [:write, id, data]
|
|
493
|
-
|
|
505
|
+
wakeup rescue nil
|
|
494
506
|
end
|
|
495
507
|
end
|
|
496
508
|
|
|
@@ -506,7 +518,7 @@ module Raptor
|
|
|
506
518
|
def attach_http2_body(id, stream_id, body, finished)
|
|
507
519
|
attached = AtomicBoolean.new(false)
|
|
508
520
|
@io_queue << [:attach_http2, id, stream_id, body, attached, finished]
|
|
509
|
-
|
|
521
|
+
wakeup rescue nil
|
|
510
522
|
@io_applied.wait { attached.true? }
|
|
511
523
|
return false if body.closed?
|
|
512
524
|
|
|
@@ -527,7 +539,7 @@ module Raptor
|
|
|
527
539
|
return if @detached_count.value.zero?
|
|
528
540
|
|
|
529
541
|
@io_queue << [:resume_http2, id]
|
|
530
|
-
|
|
542
|
+
wakeup rescue nil
|
|
531
543
|
end
|
|
532
544
|
|
|
533
545
|
# Cancels a detached response stream.
|
|
@@ -541,7 +553,7 @@ module Raptor
|
|
|
541
553
|
return if @detached_count.value.zero?
|
|
542
554
|
|
|
543
555
|
@io_queue << [:cancel_http2, id, stream_id]
|
|
544
|
-
|
|
556
|
+
wakeup rescue nil
|
|
545
557
|
end
|
|
546
558
|
|
|
547
559
|
# Waits for detached responses to finish, then cancels any that outlive
|
|
@@ -554,7 +566,7 @@ module Raptor
|
|
|
554
566
|
def drain_detached_bodies(timeout)
|
|
555
567
|
barrier = AtomicBoolean.new(false)
|
|
556
568
|
@io_queue << [:barrier, nil, barrier]
|
|
557
|
-
|
|
569
|
+
wakeup rescue nil
|
|
558
570
|
@io_applied.wait { barrier.true? }
|
|
559
571
|
|
|
560
572
|
Timeout.timeout(timeout) do
|
|
@@ -562,7 +574,7 @@ module Raptor
|
|
|
562
574
|
end
|
|
563
575
|
rescue Timeout::Error
|
|
564
576
|
@io_queue << [:cancel_all]
|
|
565
|
-
|
|
577
|
+
wakeup rescue nil
|
|
566
578
|
@detached_drained.wait { @detached_count.value.zero? }
|
|
567
579
|
end
|
|
568
580
|
|
|
@@ -617,7 +629,7 @@ module Raptor
|
|
|
617
629
|
return unless socket
|
|
618
630
|
|
|
619
631
|
@queue << socket
|
|
620
|
-
|
|
632
|
+
wakeup
|
|
621
633
|
rescue ClosedQueueError
|
|
622
634
|
socket.close
|
|
623
635
|
end
|
|
@@ -630,7 +642,7 @@ module Raptor
|
|
|
630
642
|
# @rbs (Integer id) -> void
|
|
631
643
|
def close_connection(id)
|
|
632
644
|
@io_queue << [:close, id]
|
|
633
|
-
|
|
645
|
+
wakeup rescue nil
|
|
634
646
|
end
|
|
635
647
|
|
|
636
648
|
# Closes the registration queue and wakes the selector so the
|
|
@@ -641,7 +653,7 @@ module Raptor
|
|
|
641
653
|
# @rbs () -> void
|
|
642
654
|
def shutdown
|
|
643
655
|
@queue.close
|
|
644
|
-
|
|
656
|
+
wakeup
|
|
645
657
|
end
|
|
646
658
|
|
|
647
659
|
# Returns the number of complete requests either being processed
|
|
@@ -656,6 +668,17 @@ module Raptor
|
|
|
656
668
|
|
|
657
669
|
private
|
|
658
670
|
|
|
671
|
+
# Wakes the event loop, including work queued before it starts waiting.
|
|
672
|
+
#
|
|
673
|
+
# @rbs () -> void
|
|
674
|
+
def wakeup
|
|
675
|
+
selector = @selector
|
|
676
|
+
return unless selector
|
|
677
|
+
|
|
678
|
+
selector.push(@wakeup)
|
|
679
|
+
selector.wakeup
|
|
680
|
+
end
|
|
681
|
+
|
|
659
682
|
# Returns whether shutdown has no registrations or writes left to drain.
|
|
660
683
|
#
|
|
661
684
|
# @return [Boolean]
|
|
@@ -760,7 +783,7 @@ module Raptor
|
|
|
760
783
|
dispatch = proc { |callback| @thread_pool << callback }
|
|
761
784
|
wake = proc do
|
|
762
785
|
@io_queue << [:ready_http1, id]
|
|
763
|
-
|
|
786
|
+
wakeup rescue nil
|
|
764
787
|
end
|
|
765
788
|
unless body.attach([io.budget, @detached_budget], wake, dispatch, finished)
|
|
766
789
|
socket.close rescue nil
|
|
@@ -771,7 +794,7 @@ module Raptor
|
|
|
771
794
|
@socket_to_state[socket] = { id: id, protocol: :http1, detached: true }
|
|
772
795
|
@id_to_io[id] = io
|
|
773
796
|
@detached_count.swap { |count| count + 1 }
|
|
774
|
-
|
|
797
|
+
update_interests(id, io)
|
|
775
798
|
end
|
|
776
799
|
|
|
777
800
|
# Writes buffered HTTP/1.x body chunks without blocking.
|
|
@@ -803,7 +826,7 @@ module Raptor
|
|
|
803
826
|
|
|
804
827
|
if !io.finishing && !io.wait && io.body&.next_size
|
|
805
828
|
@io_queue << [:ready_http1, id]
|
|
806
|
-
|
|
829
|
+
wakeup rescue nil
|
|
807
830
|
end
|
|
808
831
|
end
|
|
809
832
|
|
|
@@ -823,7 +846,7 @@ module Raptor
|
|
|
823
846
|
body.finish(:closed)
|
|
824
847
|
detached_body_removed
|
|
825
848
|
@id_to_io.delete(id)
|
|
826
|
-
deregister(socket
|
|
849
|
+
deregister(socket)
|
|
827
850
|
clear_write_timeout(io)
|
|
828
851
|
|
|
829
852
|
if io.state[:keep_alive]
|
|
@@ -887,7 +910,7 @@ module Raptor
|
|
|
887
910
|
|
|
888
911
|
wake = proc do
|
|
889
912
|
@io_queue << [:ready_http2, id, stream_id]
|
|
890
|
-
|
|
913
|
+
wakeup rescue nil
|
|
891
914
|
end
|
|
892
915
|
return unless body.attach([io.budget, @detached_budget], wake, dispatch, finished)
|
|
893
916
|
|
|
@@ -967,7 +990,7 @@ module Raptor
|
|
|
967
990
|
|
|
968
991
|
if !io.wait && io.output.empty? && !io.ready.empty?
|
|
969
992
|
@io_queue << [:flush_http2, id]
|
|
970
|
-
|
|
993
|
+
wakeup rescue nil
|
|
971
994
|
end
|
|
972
995
|
end
|
|
973
996
|
|
|
@@ -1133,7 +1156,7 @@ module Raptor
|
|
|
1133
1156
|
elsif io.closing
|
|
1134
1157
|
remove_connection(id)
|
|
1135
1158
|
else
|
|
1136
|
-
|
|
1159
|
+
update_interests(id, io)
|
|
1137
1160
|
end
|
|
1138
1161
|
end
|
|
1139
1162
|
|
|
@@ -1148,7 +1171,7 @@ module Raptor
|
|
|
1148
1171
|
def wait_for_write(id, io, readiness)
|
|
1149
1172
|
io.wait = readiness
|
|
1150
1173
|
track_write_timeout(id, io)
|
|
1151
|
-
|
|
1174
|
+
update_interests(id, io)
|
|
1152
1175
|
end
|
|
1153
1176
|
|
|
1154
1177
|
# Updates selector interest for one reactor-owned connection.
|
|
@@ -1158,26 +1181,34 @@ module Raptor
|
|
|
1158
1181
|
# @return [void]
|
|
1159
1182
|
#
|
|
1160
1183
|
# @rbs (Integer id, ConnectionIO io) -> void
|
|
1161
|
-
def
|
|
1184
|
+
def update_interests(id, io)
|
|
1162
1185
|
socket = @id_to_socket[id]
|
|
1163
1186
|
return unless socket && io
|
|
1164
1187
|
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
:r
|
|
1171
|
-
elsif write
|
|
1172
|
-
:w
|
|
1173
|
-
end
|
|
1188
|
+
events = 0
|
|
1189
|
+
events |= IO::READABLE if io.reading || io.wait == :read
|
|
1190
|
+
events |= IO::WRITABLE if io.wait == :write
|
|
1191
|
+
wait_for_io(socket, events)
|
|
1192
|
+
end
|
|
1174
1193
|
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1194
|
+
# Waits for a connection's next readable or writable event.
|
|
1195
|
+
#
|
|
1196
|
+
# @rbs (TCPSocket socket, Integer events) -> void
|
|
1197
|
+
def wait_for_io(socket, events)
|
|
1198
|
+
waiter = @waiters[socket]
|
|
1199
|
+
return if waiter && waiter[1] == events
|
|
1200
|
+
|
|
1201
|
+
deregister(socket)
|
|
1202
|
+
return if events.zero?
|
|
1203
|
+
|
|
1204
|
+
fiber = Fiber.new do
|
|
1205
|
+
readiness = @selector.io_wait(Fiber.current, socket, events)
|
|
1206
|
+
@ready << [socket, readiness] if readiness
|
|
1207
|
+
ensure
|
|
1208
|
+
@waiters.delete(socket)
|
|
1180
1209
|
end
|
|
1210
|
+
@waiters[socket] = [fiber, events]
|
|
1211
|
+
fiber.transfer
|
|
1181
1212
|
end
|
|
1182
1213
|
|
|
1183
1214
|
# Starts or refreshes one connection's non-blocking write deadline.
|
|
@@ -1210,19 +1241,15 @@ module Raptor
|
|
|
1210
1241
|
# Removes a socket from selector tracking.
|
|
1211
1242
|
#
|
|
1212
1243
|
# @param socket [TCPSocket] socket to deregister
|
|
1213
|
-
# @param io [ConnectionIO, nil] connection I/O state
|
|
1214
1244
|
# @return [void]
|
|
1215
1245
|
#
|
|
1216
|
-
# @rbs (TCPSocket socket
|
|
1217
|
-
def deregister(socket
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
@selector.deregister(socket)
|
|
1221
|
-
io.monitor = nil if io
|
|
1222
|
-
rescue IOError
|
|
1246
|
+
# @rbs (TCPSocket socket) -> void
|
|
1247
|
+
def deregister(socket)
|
|
1248
|
+
waiter = @waiters.delete(socket)
|
|
1249
|
+
waiter[0].transfer if waiter
|
|
1223
1250
|
end
|
|
1224
1251
|
|
|
1225
|
-
# Registers a socket
|
|
1252
|
+
# Registers a socket for readiness and sets up timeout tracking.
|
|
1226
1253
|
#
|
|
1227
1254
|
# @param socket [TCPSocket] the socket to register
|
|
1228
1255
|
# @return [void]
|
|
@@ -1235,9 +1262,9 @@ module Raptor
|
|
|
1235
1262
|
if state[:protocol] == :http2
|
|
1236
1263
|
io = @id_to_io[state[:id]]
|
|
1237
1264
|
io.reading = true
|
|
1238
|
-
|
|
1265
|
+
update_interests(state[:id], io)
|
|
1239
1266
|
else
|
|
1240
|
-
|
|
1267
|
+
wait_for_io(socket, IO::READABLE)
|
|
1241
1268
|
end
|
|
1242
1269
|
|
|
1243
1270
|
now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
@@ -1301,17 +1328,17 @@ module Raptor
|
|
|
1301
1328
|
# Dispatches readable and writable events without allowing application
|
|
1302
1329
|
# threads to take ownership of HTTP/2 sockets.
|
|
1303
1330
|
#
|
|
1304
|
-
# @param
|
|
1331
|
+
# @param socket [TCPSocket] ready client socket
|
|
1332
|
+
# @param events [Integer] readiness events
|
|
1305
1333
|
# @return [void]
|
|
1306
1334
|
#
|
|
1307
|
-
# @rbs (
|
|
1308
|
-
def
|
|
1309
|
-
socket = monitor.value
|
|
1335
|
+
# @rbs (TCPSocket socket, Integer events) -> void
|
|
1336
|
+
def handle_ready(socket, events)
|
|
1310
1337
|
state = @socket_to_state[socket]
|
|
1311
1338
|
return unless state
|
|
1312
1339
|
|
|
1313
1340
|
if state[:detached]
|
|
1314
|
-
|
|
1341
|
+
handle_http1_detached_ready(socket, events, state[:id])
|
|
1315
1342
|
return
|
|
1316
1343
|
end
|
|
1317
1344
|
|
|
@@ -1325,7 +1352,7 @@ module Raptor
|
|
|
1325
1352
|
return unless io
|
|
1326
1353
|
|
|
1327
1354
|
wait = io.wait
|
|
1328
|
-
if (wait == :read &&
|
|
1355
|
+
if (wait == :read && events.anybits?(IO::READABLE)) || (wait == :write && events.anybits?(IO::WRITABLE))
|
|
1329
1356
|
flush_output(id, io)
|
|
1330
1357
|
return unless @id_to_socket.key?(id)
|
|
1331
1358
|
return if io.wait == :read
|
|
@@ -1333,40 +1360,43 @@ module Raptor
|
|
|
1333
1360
|
flush_http2_detached_bodies(id) unless io.detached.empty?
|
|
1334
1361
|
end
|
|
1335
1362
|
|
|
1336
|
-
return unless io.reading &&
|
|
1363
|
+
return unless io.reading && events.anybits?(IO::READABLE)
|
|
1337
1364
|
|
|
1338
1365
|
io.reading = false
|
|
1339
|
-
|
|
1366
|
+
update_interests(id, io)
|
|
1340
1367
|
client = @id_to_timeout.delete(id)
|
|
1341
1368
|
@timeouts.delete!(client) if client
|
|
1342
1369
|
read_and_queue_for_parse(socket, state)
|
|
1370
|
+
ensure
|
|
1371
|
+
io = @id_to_io[state[:id]] if state
|
|
1372
|
+
update_interests(state[:id], io) if io
|
|
1343
1373
|
end
|
|
1344
1374
|
|
|
1345
1375
|
# Handles readiness for an HTTP/1.x detached response.
|
|
1346
1376
|
#
|
|
1347
|
-
# @param
|
|
1377
|
+
# @param socket [TCPSocket] ready client socket
|
|
1378
|
+
# @param events [Integer] readiness events
|
|
1348
1379
|
# @param id [Integer] unique connection identifier
|
|
1349
1380
|
# @return [void]
|
|
1350
1381
|
#
|
|
1351
|
-
# @rbs (
|
|
1352
|
-
def
|
|
1353
|
-
socket = monitor.value
|
|
1382
|
+
# @rbs (TCPSocket socket, Integer events, Integer id) -> void
|
|
1383
|
+
def handle_http1_detached_ready(socket, events, id)
|
|
1354
1384
|
io = @id_to_io[id]
|
|
1355
1385
|
return unless io.is_a?(Http1IO)
|
|
1356
1386
|
|
|
1357
1387
|
wait = io.wait
|
|
1358
|
-
if (wait == :read &&
|
|
1388
|
+
if (wait == :read && events.anybits?(IO::READABLE)) || (wait == :write && events.anybits?(IO::WRITABLE))
|
|
1359
1389
|
flush_output(id, io)
|
|
1360
1390
|
return unless @id_to_io.key?(id)
|
|
1361
1391
|
|
|
1362
1392
|
flush_http1_detached_body(id) unless io.wait
|
|
1363
1393
|
end
|
|
1364
1394
|
|
|
1365
|
-
return unless io.reading &&
|
|
1395
|
+
return unless io.reading && events.anybits?(IO::READABLE)
|
|
1366
1396
|
|
|
1367
1397
|
io.input << socket.read_nonblock(CHUNK_SIZE)
|
|
1368
1398
|
io.reading = false
|
|
1369
|
-
|
|
1399
|
+
update_interests(id, io)
|
|
1370
1400
|
rescue IO::WaitReadable
|
|
1371
1401
|
rescue IO::WaitWritable
|
|
1372
1402
|
wait_for_write(id, io, :write)
|
|
@@ -1382,7 +1412,7 @@ module Raptor
|
|
|
1382
1412
|
#
|
|
1383
1413
|
# @rbs (TCPSocket socket) -> void
|
|
1384
1414
|
def wakeup!(socket)
|
|
1385
|
-
|
|
1415
|
+
deregister(socket)
|
|
1386
1416
|
state = @socket_to_state[socket]
|
|
1387
1417
|
client = @id_to_timeout.delete(state[:id])
|
|
1388
1418
|
@timeouts.delete!(client) if client
|
|
@@ -1433,7 +1463,7 @@ module Raptor
|
|
|
1433
1463
|
socket.read_nonblock(CHUNK_SIZE)
|
|
1434
1464
|
rescue IO::WaitReadable
|
|
1435
1465
|
@queue << socket
|
|
1436
|
-
|
|
1466
|
+
wakeup
|
|
1437
1467
|
return
|
|
1438
1468
|
rescue EOFError, IOError, SystemCallError, OpenSSL::SSL::SSLError
|
|
1439
1469
|
cleanup(socket)
|
|
@@ -1461,7 +1491,7 @@ module Raptor
|
|
|
1461
1491
|
def cleanup(socket)
|
|
1462
1492
|
state = @socket_to_state.delete(socket)
|
|
1463
1493
|
io = @id_to_io.delete(state[:id])
|
|
1464
|
-
deregister(socket
|
|
1494
|
+
deregister(socket)
|
|
1465
1495
|
@id_to_socket.delete(state[:id])
|
|
1466
1496
|
@id_to_writer.delete(state[:id])
|
|
1467
1497
|
@id_to_flow_control.delete(state[:id])&.close
|
data/lib/raptor/version.rb
CHANGED
data/lib/raptor.rb
CHANGED
|
@@ -8,7 +8,7 @@ require_relative "raptor/detached_body"
|
|
|
8
8
|
#
|
|
9
9
|
# Raptor is a high-performance, preloading, multi-process, multi-threaded Ruby 4+ web server
|
|
10
10
|
# implementing Rack 3+, leveraging Ractors for parallel HTTP/1.1 and HTTP/2 request processing,
|
|
11
|
-
# native C extensions for HTTP parsing and HPACK compression, and
|
|
11
|
+
# native C extensions for HTTP parsing and HPACK compression, and io-event for non-blocking I/O.
|
|
12
12
|
#
|
|
13
13
|
module Raptor
|
|
14
14
|
end
|
|
@@ -56,8 +56,6 @@ module Raptor
|
|
|
56
56
|
|
|
57
57
|
attr_accessor closing: bool
|
|
58
58
|
|
|
59
|
-
attr_accessor monitor: NIO::Monitor?
|
|
60
|
-
|
|
61
59
|
attr_accessor timeout: TimeoutClient?
|
|
62
60
|
|
|
63
61
|
attr_reader output: Array[String]
|
|
@@ -131,13 +129,17 @@ module Raptor
|
|
|
131
129
|
def empty?: () -> bool
|
|
132
130
|
end
|
|
133
131
|
|
|
134
|
-
@io_applied: AtomicConditionVariable
|
|
135
|
-
|
|
136
132
|
@io_queue: AtomicQueue
|
|
137
133
|
|
|
138
134
|
@queue: Queue[TCPSocket]
|
|
139
135
|
|
|
140
|
-
@
|
|
136
|
+
@ready: Array[[ TCPSocket, Integer ]]
|
|
137
|
+
|
|
138
|
+
@waiters: Hash[TCPSocket, [ Fiber, Integer ]]
|
|
139
|
+
|
|
140
|
+
@wakeup: Fiber?
|
|
141
|
+
|
|
142
|
+
@selector: untyped
|
|
141
143
|
|
|
142
144
|
@http2_keepalive_timeout: Integer
|
|
143
145
|
|
|
@@ -159,6 +161,8 @@ module Raptor
|
|
|
159
161
|
|
|
160
162
|
@http1: Http1
|
|
161
163
|
|
|
164
|
+
@io_applied: AtomicConditionVariable
|
|
165
|
+
|
|
162
166
|
@timeouts: RedBlackTree[TimeoutClient]
|
|
163
167
|
|
|
164
168
|
@id_to_socket: Hash[Integer, TCPSocket]
|
|
@@ -422,6 +426,11 @@ module Raptor
|
|
|
422
426
|
|
|
423
427
|
private
|
|
424
428
|
|
|
429
|
+
# Wakes the event loop, including work queued before it starts waiting.
|
|
430
|
+
#
|
|
431
|
+
# @rbs () -> void
|
|
432
|
+
def wakeup: () -> void
|
|
433
|
+
|
|
425
434
|
# Returns whether shutdown has no registrations or writes left to drain.
|
|
426
435
|
#
|
|
427
436
|
# @return [Boolean]
|
|
@@ -603,7 +612,12 @@ module Raptor
|
|
|
603
612
|
# @return [void]
|
|
604
613
|
#
|
|
605
614
|
# @rbs (Integer id, ConnectionIO io) -> void
|
|
606
|
-
def
|
|
615
|
+
def update_interests: (Integer id, ConnectionIO io) -> void
|
|
616
|
+
|
|
617
|
+
# Waits for a connection's next readable or writable event.
|
|
618
|
+
#
|
|
619
|
+
# @rbs (TCPSocket socket, Integer events) -> void
|
|
620
|
+
def wait_for_io: (TCPSocket socket, Integer events) -> void
|
|
607
621
|
|
|
608
622
|
# Starts or refreshes one connection's non-blocking write deadline.
|
|
609
623
|
#
|
|
@@ -625,13 +639,12 @@ module Raptor
|
|
|
625
639
|
# Removes a socket from selector tracking.
|
|
626
640
|
#
|
|
627
641
|
# @param socket [TCPSocket] socket to deregister
|
|
628
|
-
# @param io [ConnectionIO, nil] connection I/O state
|
|
629
642
|
# @return [void]
|
|
630
643
|
#
|
|
631
|
-
# @rbs (TCPSocket socket
|
|
632
|
-
def deregister: (TCPSocket socket
|
|
644
|
+
# @rbs (TCPSocket socket) -> void
|
|
645
|
+
def deregister: (TCPSocket socket) -> void
|
|
633
646
|
|
|
634
|
-
# Registers a socket
|
|
647
|
+
# Registers a socket for readiness and sets up timeout tracking.
|
|
635
648
|
#
|
|
636
649
|
# @param socket [TCPSocket] the socket to register
|
|
637
650
|
# @return [void]
|
|
@@ -661,20 +674,22 @@ module Raptor
|
|
|
661
674
|
# Dispatches readable and writable events without allowing application
|
|
662
675
|
# threads to take ownership of HTTP/2 sockets.
|
|
663
676
|
#
|
|
664
|
-
# @param
|
|
677
|
+
# @param socket [TCPSocket] ready client socket
|
|
678
|
+
# @param events [Integer] readiness events
|
|
665
679
|
# @return [void]
|
|
666
680
|
#
|
|
667
|
-
# @rbs (
|
|
668
|
-
def
|
|
681
|
+
# @rbs (TCPSocket socket, Integer events) -> void
|
|
682
|
+
def handle_ready: (TCPSocket socket, Integer events) -> void
|
|
669
683
|
|
|
670
684
|
# Handles readiness for an HTTP/1.x detached response.
|
|
671
685
|
#
|
|
672
|
-
# @param
|
|
686
|
+
# @param socket [TCPSocket] ready client socket
|
|
687
|
+
# @param events [Integer] readiness events
|
|
673
688
|
# @param id [Integer] unique connection identifier
|
|
674
689
|
# @return [void]
|
|
675
690
|
#
|
|
676
|
-
# @rbs (
|
|
677
|
-
def
|
|
691
|
+
# @rbs (TCPSocket socket, Integer events, Integer id) -> void
|
|
692
|
+
def handle_http1_detached_ready: (TCPSocket socket, Integer events, Integer id) -> void
|
|
678
693
|
|
|
679
694
|
# Deregisters a readable socket and resumes its idle keep-alive
|
|
680
695
|
# connection or queues its bytes for parsing.
|
data/sig/generated/raptor.rbs
CHANGED
|
@@ -4,6 +4,6 @@
|
|
|
4
4
|
#
|
|
5
5
|
# Raptor is a high-performance, preloading, multi-process, multi-threaded Ruby 4+ web server
|
|
6
6
|
# implementing Rack 3+, leveraging Ractors for parallel HTTP/1.1 and HTTP/2 request processing,
|
|
7
|
-
# native C extensions for HTTP parsing and HPACK compression, and
|
|
7
|
+
# native C extensions for HTTP parsing and HPACK compression, and io-event for non-blocking I/O.
|
|
8
8
|
module Raptor
|
|
9
9
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: raptor
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.25.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Joshua Young
|
|
@@ -24,7 +24,7 @@ dependencies:
|
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
25
|
version: 3.2.0
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
|
-
name:
|
|
27
|
+
name: io-event
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
29
29
|
requirements:
|
|
30
30
|
- - ">="
|