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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c8c3462777a399cad50b6131c497c98ab519850ff1d88d062b681cc05c9d540b
4
- data.tar.gz: 878a2629b500d8873836cda4bd463f0dcb727a33bd301fc5a246cd860a3f0957
3
+ metadata.gz: 59fe5e87d01266b5c1c95e08e24339fc1bae9748c9ed814d4694903a2bbce8c5
4
+ data.tar.gz: 53cb18d26ad63f298a7a94496c536b561de3c7be29113df8ee77736d20c9019e
5
5
  SHA512:
6
- metadata.gz: 0d9b05f416a7024c91dc2861d6f748eadb1c20e01224c3e82a1202247f48220e56f81742fa600f41f1885c60587464b9506c0e2855d9392767016f5199bb0d94
7
- data.tar.gz: 93403bcdbfaef05e6a011cc795ef66b7713dc2ed4266c157afb3f5eb1b53ae60c8f7610e60d2caee75e8b82716e58cac6b771543d6f9d43823cb03e5eed87dd8
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
- NIO for non-blocking I/O and Ractors for parallel HTTP/1.1 and HTTP/2 parsing via native C extensions, which also
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.24.0 vs Puma 8.0.2 vs Falcon 0.57.0. Each case has 3 fresh-process samples, interleaved in seeded shuffled
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.32k ±0.2% | - | 50.10 | - | 2.387 | 364.0 |
282
- | Raptor | Scaling (3–16) | - | 8.10k ±0.3% | - | 22.45 | - | 0.514 | 340.8 |
283
- | Puma | Fixed (3) | Fixed (3) | 1.55k ±0.9% | 53.4% lower | 121.78 | 143.1% higher | 0.737 | 283.8 |
284
- | Puma | Scaling (3–16) | Scaling (3–16) | 8.13k ±0.7% | 0.4% higher | 22.41 | 0.1% lower | 0.481 | 341.2 |
285
- | Falcon | Fibers | Fixed (3) | 10.65k ±4.1% | 220.8% higher | 16.18 | 67.7% lower | 0.450 | 425.5 |
286
- | Falcon | Fibers | Scaling (3–16) | 10.65k ±4.1% | 31.5% higher | 16.18 | 27.9% lower | 0.450 | 425.5 |
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.01k ±8.2% | - | 56.38 | - | 2.306 | 365.0 |
293
- | Raptor | Scaling (3–16) | - | 7.55k ±0.6% | - | 24.18 | - | 0.500 | 363.7 |
294
- | Raptor | Fixed (16) | - | 7.56k ±0.7% | - | 24.16 | - | 0.468 | 367.8 |
295
- | Puma | Fixed (3) | Fixed (3) | 1.49k ±0.2% | 50.4% lower | 105.33 | 86.8% higher | 0.784 | 290.7 |
296
- | Puma | Scaling (3–16) | Scaling (3–16) | 7.63k ±0.9% | 1.1% higher | 23.89 | 1.2% lower | 0.466 | 329.9 |
297
- | Puma | Fixed (16) | Fixed (16) | 7.73k ±0.5% | 2.2% higher | 23.55 | 2.5% lower | 0.461 | 332.3 |
298
- | Falcon | Fibers | Fixed (3) | 7.54k ±1.8% | 150.8% higher | 24.40 | 56.7% lower | 0.373 | 357.4 |
299
- | Falcon | Fibers | Scaling (3–16) | 7.54k ±1.8% | 0.1% lower | 24.40 | 0.9% higher | 0.373 | 357.4 |
300
- | Falcon | Fibers | Fixed (16) | 7.54k ±1.8% | 0.2% lower | 24.40 | 1.0% higher | 0.373 | 357.4 |
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 | vs Raptor req/s | p95 ms | vs Raptor p95 | CPU ms/req | PSS MiB |
305
- | ------ | -------------- | --------------- | ----------- | --------------- | ------ | ------------- | ---------- | ------- |
306
- | Raptor | Fixed (3) | - | 1.60k ±6.4% | - | 119.04 | - | 0.779 | 418.0 |
307
- | Raptor | Scaling (3–16) | - | 7.98k ±9.9% | - | 23.38 | - | 0.565 | 894.4 |
308
- | Falcon | Fibers | Fixed (3) | 7.18k ±1.3% | 348.7% higher | 26.29 | 77.9% lower | 0.438 | 515.8 |
309
- | Falcon | Fibers | Scaling (3–16) | 7.18k ±1.3% | 10.0% lower | 26.29 | 12.4% higher | 0.438 | 515.8 |
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.13k ±0.3% | - | 72.60 | - | 2.673 | 526.0 |
316
- | Raptor | Scaling (3–16) | - | 3.22k ±2.0% | - | 68.49 | - | 2.546 | 520.0 |
317
- | Puma | Fixed (3) | Fixed (3) | 2.98k ±0.7% | 4.8% lower | 62.70 | 13.6% lower | 2.615 | 474.7 |
318
- | Puma | Scaling (3–16) | Scaling (3–16) | 2.64k ±3.2% | 17.9% lower | 59.81 | 12.7% lower | 2.522 | 567.4 |
319
- | Falcon | Fibers | Fixed (3) | 3.65k ±7.0% | 16.4% higher | 46.10 | 36.5% lower | 2.311 | 389.2 |
320
- | Falcon | Fibers | Scaling (3–16) | 3.65k ±7.0% | 13.3% higher | 46.10 | 32.7% lower | 2.311 | 389.2 |
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) | - | 2.88k ±1.6% | - | 57.40 | - | 2.721 | 515.4 |
327
- | Raptor | Scaling (3–16) | - | 2.81k ±3.8% | - | 56.14 | - | 2.721 | 528.2 |
328
- | Puma | Fixed (3) | Fixed (3) | 3.24k ±0.7% | 12.3% higher | 60.73 | 5.8% higher | 2.449 | 406.4 |
329
- | Puma | Scaling (3–16) | Scaling (3–16) | 2.71k ±3.6% | 3.3% lower | 70.56 | 25.7% higher | 2.459 | 487.6 |
330
- | Falcon | Fibers | Fixed (3) | 3.62k ±1.0% | 25.8% higher | 62.03 | 8.1% higher | 2.369 | 542.0 |
331
- | Falcon | Fibers | Scaling (3–16) | 3.62k ±1.0% | 29.1% higher | 62.03 | 10.5% higher | 2.369 | 542.0 |
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.12k ±1.3% | - | 65.66 | - | 2.439 | 587.6 |
338
- | Raptor | Scaling (3–16) | - | 3.15k ±0.4% | - | 74.95 | - | 2.344 | 609.0 |
339
- | Falcon | Fibers | Fixed (3) | 3.49k ±20.7% | 11.7% higher | 120.58 | 83.6% higher | 2.309 | 536.3 |
340
- | Falcon | Fibers | Scaling (3–16) | 3.49k ±20.7% | 10.7% higher | 120.58 | 60.9% higher | 2.309 | 536.3 |
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 | vs Raptor req/s | p95 ms | vs Raptor p95 | CPU ms/req | PSS MiB |
345
- | ------ | -------------- | --------------- | ------------ | --------------- | ------ | ------------- | ---------- | ------- |
346
- | Raptor | Scaling (3–16) | - | 96.13k ±0.8% | - | 3.68 | - | 0.048 | 512.3 |
347
- | Puma | Scaling (3–16) | Scaling (3–16) | 83.26k ±0.0% | 13.4% lower | 3.94 | 7.3% higher | 0.055 | 1344.6 |
348
- | Falcon | Fibers | Scaling (3–16) | 98.30k ±0.5% | 2.3% higher | 3.89 | 5.7% higher | 0.051 | 471.5 |
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 | vs Raptor req/s | p95 ms | vs Raptor p95 | CPU ms/req | PSS MiB |
353
- | ------------- | -------------- | --------------- | ------------ | --------------- | ------ | ------------- | ---------- | ------- |
354
- | Raptor | Fixed (3) | - | 3.01k ±4.9% | - | 51.22 | - | 2.286 | 369.6 |
355
- | Raptor | Scaling (3–16) | - | 7.49k ±0.8% | - | 24.39 | - | 0.488 | 372.7 |
356
- | Puma | Fixed (3) | Fixed (3) | 0.39k ±13.8% | 87.0% lower | 314.80 | 514.6% higher | 1.250 | 282.9 |
357
- | Puma | Scaling (3–16) | Scaling (3–16) | 7.51k ±0.4% | 0.4% higher | 24.23 | 0.6% lower | 0.464 | 336.3 |
358
- | Falcon | Fibers | Fixed (3) | 7.57k ±4.4% | 151.9% higher | 24.04 | 53.1% lower | 0.375 | 355.5 |
359
- | Falcon | Fibers | Scaling (3–16) | 7.57k ±4.4% | 1.2% higher | 24.04 | 1.4% lower | 0.375 | 355.5 |
360
- | Raptor (enum) | Fixed (3) | - | 0.88k ±0.3% | - | 63.76 | - | 7.972 | 362.6 |
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 28 timeouts, 1 stalled stream across all samples.
362
+ Puma, Fixed (3) had 34 timeouts, 1 stalled stream across all samples.
363
363
 
364
- Raptor (enum), Fixed (3) had 29 timeouts across all samples.
364
+ Raptor (enum), Fixed (3) had 24 timeouts across all samples.
365
365
 
366
- > ruby 4.1.0dev (2026-10-27T15:28:18Z HEAD 33ac6afea7) +YJIT +PRISM [aarch64-linux]
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.
@@ -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 | `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/>NIO::Selector<br/>read_nonblock 64KB<br/>Red-Black-Tree timeouts"]
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>Like Puma, it uses [`nio4r`](https://github.com/socketry/nio4r), backed by `epoll` on Linux
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,
@@ -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 "nio"
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: NIO::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 = NIO::Selector.new
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
- @selector.select(timeout) do |monitor|
271
- handle_monitor(monitor)
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
- @selector.wakeup
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
- @selector.wakeup
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
- @selector.wakeup rescue nil
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
- @selector.wakeup rescue nil
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
- @selector.wakeup rescue nil
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
- @selector.wakeup rescue nil
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
- @selector.wakeup rescue nil
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
- @selector.wakeup rescue nil
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
- @selector.wakeup rescue nil
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
- @selector.wakeup rescue nil
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
- @selector.wakeup
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
- @selector.wakeup rescue nil
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
- @selector.wakeup
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
- @selector.wakeup rescue nil
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
- update_monitor(id, io)
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
- @selector.wakeup rescue nil
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, io)
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
- @selector.wakeup rescue nil
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
- @selector.wakeup rescue nil
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
- update_monitor(id, io)
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
- update_monitor(id, io)
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 update_monitor(id, io)
1184
+ def update_interests(id, io)
1162
1185
  socket = @id_to_socket[id]
1163
1186
  return unless socket && io
1164
1187
 
1165
- read = io.reading || io.wait == :read
1166
- write = io.wait == :write
1167
- interests = if read && write
1168
- :rw
1169
- elsif read
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
- if io.monitor
1176
- io.monitor.interests = interests
1177
- elsif interests
1178
- io.monitor = @selector.register(socket, interests)
1179
- io.monitor.value = socket
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, ConnectionIO? io) -> void
1217
- def deregister(socket, io)
1218
- return unless io&.monitor || @selector.registered?(socket)
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 with the NIO selector and sets up timeout tracking.
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
- update_monitor(state[:id], io)
1265
+ update_interests(state[:id], io)
1239
1266
  else
1240
- @selector.register(socket, :r).value = socket
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 monitor [NIO::Monitor] ready selector monitor
1331
+ # @param socket [TCPSocket] ready client socket
1332
+ # @param events [Integer] readiness events
1305
1333
  # @return [void]
1306
1334
  #
1307
- # @rbs (NIO::Monitor monitor) -> void
1308
- def handle_monitor(monitor)
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
- handle_http1_detached_monitor(monitor, state[:id])
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 && monitor.readable?) || (wait == :write && monitor.writable?)
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 && monitor.readable?
1363
+ return unless io.reading && events.anybits?(IO::READABLE)
1337
1364
 
1338
1365
  io.reading = false
1339
- update_monitor(id, io)
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 monitor [NIO::Monitor] ready selector monitor
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 (NIO::Monitor monitor, Integer id) -> void
1352
- def handle_http1_detached_monitor(monitor, id)
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 && monitor.readable?) || (wait == :write && monitor.writable?)
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 && monitor.readable?
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
- update_monitor(id, io)
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
- @selector.deregister(socket)
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
- @selector.wakeup
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, io)
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
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Raptor
5
- VERSION = "0.24.0"
5
+ VERSION = "0.25.0"
6
6
  end
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 NIO for non-blocking I/O.
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
- @selector: NIO::Selector
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 update_monitor: (Integer id, ConnectionIO io) -> void
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, ConnectionIO? io) -> void
632
- def deregister: (TCPSocket socket, ConnectionIO? io) -> void
644
+ # @rbs (TCPSocket socket) -> void
645
+ def deregister: (TCPSocket socket) -> void
633
646
 
634
- # Registers a socket with the NIO selector and sets up timeout tracking.
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 monitor [NIO::Monitor] ready selector monitor
677
+ # @param socket [TCPSocket] ready client socket
678
+ # @param events [Integer] readiness events
665
679
  # @return [void]
666
680
  #
667
- # @rbs (NIO::Monitor monitor) -> void
668
- def handle_monitor: (NIO::Monitor monitor) -> void
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 monitor [NIO::Monitor] ready selector monitor
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 (NIO::Monitor monitor, Integer id) -> void
677
- def handle_http1_detached_monitor: (NIO::Monitor monitor, Integer id) -> void
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.
@@ -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 NIO for non-blocking I/O.
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.24.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: nio4r
27
+ name: io-event
28
28
  requirement: !ruby/object:Gem::Requirement
29
29
  requirements:
30
30
  - - ">="