raptor 0.18.0 → 0.19.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 +5 -0
- data/README.md +29 -30
- data/docs/brisrails-talk.md +3 -3
- data/docs/raptor-vs-puma.md +3 -3
- data/lib/rackup/handler/raptor.rb +5 -3
- data/lib/raptor/binder.rb +9 -0
- data/lib/raptor/cli.rb +22 -12
- data/lib/raptor/cluster.rb +17 -13
- data/lib/raptor/reactor.rb +1 -1
- data/lib/raptor/version.rb +1 -1
- data/sig/generated/raptor/binder.rbs +7 -0
- data/sig/generated/raptor/cli.rbs +8 -6
- data/sig/generated/raptor/cluster.rbs +1 -1
- data/sig/generated/raptor/reactor.rbs +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6620d52a503c84e57e9aea223f0980e2215aeb58da7154e077c31c0d1858bf12
|
|
4
|
+
data.tar.gz: 36c546ae9bb960f6049a82e123af665375785872533b4657f0c336abd8ab7a9f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 729594070744ec522ec48852af6cce2c5aeef4df2050359473bdbf3f11aeaa167dbf7124e9a2fa21e622f77b6351d508fa3f4cf7438839e1b4e8a037784a7c89
|
|
7
|
+
data.tar.gz: 6812627b196892d9ffbc7608d34fc54c790d2d96ecdd4fa0823946389cc147a6e1640028cd057b958e91e9a2fc6307397e693bd5e6e7998b1c41b9fc9d13195b
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
|
@@ -36,30 +36,29 @@ run proc { |_env| [200, { "content-type" => "text/plain" }, ["Hello, World!"]] }
|
|
|
36
36
|
|
|
37
37
|
```
|
|
38
38
|
> bundle exec raptor -w 10 -t 3 hello_world.ru
|
|
39
|
-
[Raptor
|
|
40
|
-
[Raptor
|
|
41
|
-
[Raptor
|
|
42
|
-
[Raptor
|
|
43
|
-
[Raptor
|
|
44
|
-
[Raptor
|
|
45
|
-
[Raptor
|
|
46
|
-
[Raptor
|
|
47
|
-
[Raptor
|
|
48
|
-
[Raptor
|
|
49
|
-
[Raptor
|
|
50
|
-
[Raptor
|
|
51
|
-
[Raptor
|
|
52
|
-
[Raptor
|
|
53
|
-
[Raptor
|
|
54
|
-
[Raptor
|
|
55
|
-
[Raptor
|
|
56
|
-
[Raptor
|
|
57
|
-
[Raptor
|
|
58
|
-
[Raptor
|
|
59
|
-
[Raptor
|
|
60
|
-
[Raptor
|
|
61
|
-
[Raptor
|
|
62
|
-
[Raptor 83665|Main|Main] Worker 9 booted
|
|
39
|
+
[Raptor 46475|Main|Main] Cluster initializing:
|
|
40
|
+
[Raptor 46475|Main|Main] ├─ Version: 0.19.0
|
|
41
|
+
[Raptor 46475|Main|Main] ├─ Ruby Version: ruby 4.0.6 (2026-07-14 revision 03b6d3f889) +YJIT +PRISM [arm64-darwin23]
|
|
42
|
+
[Raptor 46475|Main|Main] ├─ Environment: development
|
|
43
|
+
[Raptor 46475|Main|Main] ├─ Master PID: 46475
|
|
44
|
+
[Raptor 46475|Main|Main] │ └─ 10 worker processes
|
|
45
|
+
[Raptor 46475|Main|Main] │ ├─ 1 server thread
|
|
46
|
+
[Raptor 46475|Main|Main] │ ├─ 1 reactor thread
|
|
47
|
+
[Raptor 46475|Main|Main] │ ├─ 1 HTTP/1.1 pipeline ractor
|
|
48
|
+
[Raptor 46475|Main|Main] │ ├─ 1 pipeline collector thread
|
|
49
|
+
[Raptor 46475|Main|Main] │ ├─ 3 worker threads (scaling, no limit)
|
|
50
|
+
[Raptor 46475|Main|Main] │ └─ 1 stats thread
|
|
51
|
+
[Raptor 46475|Main|Main] └─ Listening on 0.0.0.0:9292
|
|
52
|
+
[Raptor 46480|Main|Main] Worker 0 booted
|
|
53
|
+
[Raptor 46484|Main|Main] Worker 4 booted
|
|
54
|
+
[Raptor 46482|Main|Main] Worker 2 booted
|
|
55
|
+
[Raptor 46481|Main|Main] Worker 1 booted
|
|
56
|
+
[Raptor 46483|Main|Main] Worker 3 booted
|
|
57
|
+
[Raptor 46485|Main|Main] Worker 5 booted
|
|
58
|
+
[Raptor 46486|Main|Main] Worker 6 booted
|
|
59
|
+
[Raptor 46487|Main|Main] Worker 7 booted
|
|
60
|
+
[Raptor 46488|Main|Main] Worker 8 booted
|
|
61
|
+
[Raptor 46489|Main|Main] Worker 9 booted
|
|
63
62
|
```
|
|
64
63
|
|
|
65
64
|
```
|
|
@@ -93,7 +92,7 @@ The config file is a Ruby file that evaluates to a hash of options. By default R
|
|
|
93
92
|
drain_accept_queue: false,
|
|
94
93
|
workers: 4, # `Etc.nprocessors`
|
|
95
94
|
threads: 3,
|
|
96
|
-
max_threads:
|
|
95
|
+
max_threads: Float::INFINITY, # set to `threads` for a fixed pool
|
|
97
96
|
chdir: nil,
|
|
98
97
|
environment: nil, # falls back to `RAILS_ENV`, then `RACK_ENV`, then `"development"`
|
|
99
98
|
connection: {
|
|
@@ -129,10 +128,10 @@ The config file is a Ruby file that evaluates to a hash of options. By default R
|
|
|
129
128
|
}
|
|
130
129
|
```
|
|
131
130
|
|
|
132
|
-
`threads` sets the number of application threads each worker keeps running.
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
131
|
+
`threads` sets the number of application threads each worker keeps running. By default, Raptor adds temporary threads
|
|
132
|
+
without a fixed limit when queued work is held up by blocking operations. It does not add threads when waiting for the
|
|
133
|
+
GVL is the bottleneck, and temporary threads leave after the queue drains. Set `max_threads` to cap growth, or set it
|
|
134
|
+
to the same value as `threads` for a fixed pool.
|
|
136
135
|
|
|
137
136
|
## Bindings
|
|
138
137
|
|
|
@@ -207,7 +206,7 @@ Worker 1 (phase 0): pid=91351, requests=1199, busy=1/3, backlog=0, booted, last_
|
|
|
207
206
|
|
|
208
207
|
## (Micro) Benchmarks
|
|
209
208
|
|
|
210
|
-
Raptor 0.
|
|
209
|
+
Raptor 0.19.0 vs Puma 8.0.2 vs Falcon 0.57.0 across two workload profiles. **IO-bound** is a GET endpoint that
|
|
211
210
|
interleaves 5-10 short sleeps (total 2.5-15ms) with small CPU work, simulating a read path that makes several DB or
|
|
212
211
|
cache calls. **CPU-bound** is a POST endpoint that accepts a small JSON body, interleaves 3-5 chunks of JSON item
|
|
213
212
|
building (total 450-1500 items) with sub-100µs sleeps, and returns the built array, simulating a write path that does
|
data/docs/brisrails-talk.md
CHANGED
|
@@ -1085,18 +1085,18 @@ The bit that matters most in practice:
|
|
|
1085
1085
|
|
|
1086
1086
|
## Scaling app threads without making CPU contention worse
|
|
1087
1087
|
|
|
1088
|
-
The pool
|
|
1088
|
+
The pool starts at `threads` and scales automatically when more threads would help.
|
|
1089
1089
|
|
|
1090
1090
|
- <big>A native CRuby thread hook measures time running, blocked outside the GVL, and waiting for the GVL</big>
|
|
1091
1091
|
- <big>The queue has to stay non-empty, and every current worker has to be active</big>
|
|
1092
1092
|
- <big>Blocked time has to exceed half of worker time</big>
|
|
1093
1093
|
- <big>GVL wait has to stay below two percent</big>
|
|
1094
|
-
- <big>Only then does the pool add a temporary thread
|
|
1094
|
+
- <big>Only then does the pool add a temporary thread</big>
|
|
1095
1095
|
- <big>When the queue drains, temporary threads leave and the pool returns to `threads`</big>
|
|
1096
1096
|
|
|
1097
1097
|
The distinction matters. More threads help when requests are asleep in database or network calls. They make CPU-bound Ruby slower when the GVL is already the bottleneck.
|
|
1098
1098
|
|
|
1099
|
-
`max_threads
|
|
1099
|
+
Growth has no fixed limit by default. Set `max_threads` to cap it, or set it to `threads` to keep the pool fixed. OS threads still are not as cheap as fibers.
|
|
1100
1100
|
|
|
1101
1101
|
<br>
|
|
1102
1102
|
<br>
|
data/docs/raptor-vs-puma.md
CHANGED
|
@@ -38,7 +38,7 @@ The rest of this doc explains why the shape looks like that.
|
|
|
38
38
|
| ---------------------- | ------------------------------------------------------- | ---------------------------------------------------------------------------- |
|
|
39
39
|
| Ruby requirement | 3.0 and up | 4.0 and up (needs `Ractor::Port`) |
|
|
40
40
|
| Process model | Single, or cluster (pre-forks by default with 2+ workers); optional refork | Cluster only, always pre-forks |
|
|
41
|
-
| Threading model | `ThreadPool` with `Mutex` + `ConditionVariable`; autoscaling min/max, or fixed when min == max | `AtomicThreadPool` with a CAS-based queue;
|
|
41
|
+
| Threading model | `ThreadPool` with `Mutex` + `ConditionVariable`; autoscaling min/max, or fixed when min == max | `AtomicThreadPool` with a CAS-based queue; GVL-aware adaptive scaling from a fixed baseline, with an optional limit |
|
|
42
42
|
| True parallelism | One GVL inside each worker; parser runs on an app thread | Protocol Ractors can parse in parallel with the app on the pipeline path |
|
|
43
43
|
| I/O multiplexing | `nio4r` reactor for keep-alive idle and slow reads | `nio4r` reactor for the same, plus a red-black tree for O(log n) timeouts |
|
|
44
44
|
| Cluster dispatch | Workers race on inherited listeners with a load-proportional accept delay | Two-choice load-aware BPF dispatch for TCP on Linux; shared-listener fallback |
|
|
@@ -234,11 +234,11 @@ Your Rack app still runs on ordinary threads under one worker GVL, so the app do
|
|
|
234
234
|
|
|
235
235
|
**How the Ractor pools actually work.** Raptor uses the `ractor-pool` gem, which is another one of my libraries. Each pool has one coordinator Ractor and M pipeline Ractors. When a pipeline Ractor is idle, it sends itself back to the coordinator via `coordinator.send(Ractor.current, move: true)`. When work arrives at the coordinator, it either forwards it to a waiting Ractor (if any) or queues it. This coordinator-dispatch pattern guarantees that no Ractor sits idle while there is work. Results flow back through a shared `Ractor::Port` (a many-to-one channel added in recent Ruby versions and stable in 4.0) to a Ruby-side collector thread. If `M == 1` the coordinator is skipped and work goes straight to the single pipeline Ractor.
|
|
236
236
|
|
|
237
|
-
Raptor runs
|
|
237
|
+
Raptor always runs an HTTP/1.1 pool because every binding supports HTTP/1.1. It only starts an HTTP/2 pool when an SSL binding is present, since HTTP/2 is negotiated over TLS. SSL bindings still need both pools because ALPN allows each client to choose HTTP/2 or HTTP/1.1. Both pool sizes scale with headroom via `round(cores / workers)`, clamped to `[1, 3]` for `http1.ractors` and `[1, 2]` for `http2.ractors`. Keeping the pools separate means h1 and h2 parsing never share ractor slots, so a burst of small HTTP/1.1 requests cannot delay HTTP/2 frame handling on the same connection, and vice versa.
|
|
238
238
|
|
|
239
239
|
**Why a custom thread pool.** The `AtomicThreadPool` in `atomic-ruby` (another one of my libraries) is backed by an `AtomicQueue`. The queue is a Michael-Scott multi-producer, multi-consumer FIFO: a singly linked list with a dummy sentinel and atomic head and tail pointers. Producers append nodes at the tail; consumers advance the head. Both operations are O(1) and make progress through compare-and-swap rather than a queue-wide mutex. Separate atoms track queue size and active app threads for backpressure.
|
|
240
240
|
|
|
241
|
-
The pool
|
|
241
|
+
The pool starts at `threads` and scales without a fixed limit by default. Set `max_threads` to cap its growth, or set it to the same value as `threads` to keep the pool fixed. A native CRuby thread-event hook measures how much active workers spend running, blocked outside the GVL, and waiting to acquire it. The pool only adds a temporary thread after work has remained queued across several samples, every current worker is active, blocked time is above half of measured worker time, and GVL wait is below two percent. That last check matters: adding threads helps when existing threads are asleep in database or network calls, but hurts when CPU-bound Ruby threads are already fighting over the GVL. Temporary threads retire after the queue has remained empty for a second.
|
|
242
242
|
|
|
243
243
|
The pool still uses an `AtomicConditionVariable` under the hood to park idle threads (idle threads call `Thread.stop` and get woken with `Thread#wakeup`; there is no spinning), because idle spinning would waste CPU. The difference from Puma's pool is not "no locks anywhere" but rather "the hot path (enqueue and dequeue when the queue has items) is lock-free". Once every worker is busy the mechanics look similar; where things diverge is under contention when you have many threads all trying to push and pop.
|
|
244
244
|
|
|
@@ -44,7 +44,7 @@ module Rackup
|
|
|
44
44
|
"Port=PORT" => "Port to listen on (default: #{DEFAULT_OPTIONS[:Port]})",
|
|
45
45
|
"Workers=NUM" => "Number of worker processes (default: available processor count)",
|
|
46
46
|
"Threads=NUM" => "Number of threads per worker (default: 3)",
|
|
47
|
-
"MaxThreads=NUM" => "Maximum threads per worker (`unlimited` for no limit; default:
|
|
47
|
+
"MaxThreads=NUM" => "Maximum threads per worker (`unlimited` for no limit; default: unlimited)",
|
|
48
48
|
"Config=PATH" => "Load additional configuration from PATH"
|
|
49
49
|
}
|
|
50
50
|
end
|
|
@@ -71,6 +71,8 @@ module Rackup
|
|
|
71
71
|
cli_defaults = ::Raptor::CLI::DEFAULT_OPTIONS
|
|
72
72
|
config_path = options[:Config] || ::Raptor::CLI.default_config_path
|
|
73
73
|
config = config_path ? ::Raptor::CLI.load_config_file(config_path) : {}
|
|
74
|
+
threads = (options[:Threads] || config[:threads] || cli_defaults[:threads]).to_i
|
|
75
|
+
max_threads = options[:MaxThreads] || config.fetch(:max_threads, cli_defaults[:max_threads])
|
|
74
76
|
|
|
75
77
|
result = {
|
|
76
78
|
binds: if options[:Host] || options[:Port]
|
|
@@ -81,8 +83,8 @@ module Rackup
|
|
|
81
83
|
socket_backlog: (config[:socket_backlog] || cli_defaults[:socket_backlog]).to_i,
|
|
82
84
|
drain_accept_queue: config.key?(:drain_accept_queue) ? config[:drain_accept_queue] : cli_defaults[:drain_accept_queue],
|
|
83
85
|
workers: (options[:Workers] || config[:workers] || Concurrent.available_processor_count).to_i,
|
|
84
|
-
threads:
|
|
85
|
-
max_threads: ::Raptor::CLI.parse_max_threads(
|
|
86
|
+
threads: threads,
|
|
87
|
+
max_threads: ::Raptor::CLI.parse_max_threads(max_threads, threads: threads),
|
|
86
88
|
app: app
|
|
87
89
|
}
|
|
88
90
|
result[:rackup] = config[:rackup] if config.key?(:rackup)
|
data/lib/raptor/binder.rb
CHANGED
|
@@ -106,6 +106,15 @@ module Raptor
|
|
|
106
106
|
tcp_listener.local_address.ip_port
|
|
107
107
|
end
|
|
108
108
|
|
|
109
|
+
# Returns whether any listener can negotiate HTTP/2.
|
|
110
|
+
#
|
|
111
|
+
# @return [Boolean]
|
|
112
|
+
#
|
|
113
|
+
# @rbs () -> bool
|
|
114
|
+
def http2?
|
|
115
|
+
@listeners.any? { |listener| listener.is_a?(SslListener) }
|
|
116
|
+
end
|
|
117
|
+
|
|
109
118
|
# Closes all listening sockets.
|
|
110
119
|
#
|
|
111
120
|
# @return [void]
|
data/lib/raptor/cli.rb
CHANGED
|
@@ -34,7 +34,7 @@ module Raptor
|
|
|
34
34
|
drain_accept_queue: false,
|
|
35
35
|
workers: DEFAULT_WORKER_COUNT,
|
|
36
36
|
threads: 3,
|
|
37
|
-
max_threads:
|
|
37
|
+
max_threads: Float::INFINITY,
|
|
38
38
|
rackup: "config.ru",
|
|
39
39
|
chdir: nil,
|
|
40
40
|
environment: nil,
|
|
@@ -101,17 +101,27 @@ module Raptor
|
|
|
101
101
|
|
|
102
102
|
# Parses a maximum thread count from a CLI, config, or Rack handler value.
|
|
103
103
|
#
|
|
104
|
-
# @param value [Integer, Float, String
|
|
105
|
-
# @
|
|
106
|
-
#
|
|
104
|
+
# @param value [Integer, Float, String] maximum thread count
|
|
105
|
+
# @param threads [Integer] baseline thread count
|
|
106
|
+
# @return [Integer, Float] parsed thread count, or `Float::INFINITY` for
|
|
107
|
+
# `"unlimited"`
|
|
108
|
+
# @raise [ArgumentError] if the maximum is nil or less than the baseline
|
|
107
109
|
#
|
|
108
|
-
# @rbs (Integer | Float | String
|
|
109
|
-
def self.parse_max_threads(value)
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
110
|
+
# @rbs (Integer | Float | String value, threads: Integer) -> (Integer | Float)
|
|
111
|
+
def self.parse_max_threads(value, threads:)
|
|
112
|
+
raise ArgumentError, "max_threads cannot be nil" unless value
|
|
113
|
+
|
|
114
|
+
max_threads = if value == "unlimited" || value == Float::INFINITY
|
|
115
|
+
Float::INFINITY
|
|
116
|
+
elsif value.is_a?(Integer)
|
|
117
|
+
value
|
|
118
|
+
else
|
|
119
|
+
Integer(value, 10)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
raise ArgumentError, "max_threads must be greater than or equal to threads" if max_threads < threads
|
|
113
123
|
|
|
114
|
-
|
|
124
|
+
max_threads
|
|
115
125
|
end
|
|
116
126
|
|
|
117
127
|
# @rbs @command: Symbol
|
|
@@ -146,7 +156,7 @@ module Raptor
|
|
|
146
156
|
@parser.parse!(argv)
|
|
147
157
|
|
|
148
158
|
@options[:rackup] = argv.first if @command == :server && argv.first
|
|
149
|
-
@options[:max_threads] = self.class.parse_max_threads(@options[:max_threads])
|
|
159
|
+
@options[:max_threads] = self.class.parse_max_threads(@options[:max_threads], threads: @options[:threads])
|
|
150
160
|
end
|
|
151
161
|
|
|
152
162
|
# Runs the requested command.
|
|
@@ -259,7 +269,7 @@ module Raptor
|
|
|
259
269
|
@options[:threads] = num
|
|
260
270
|
end
|
|
261
271
|
|
|
262
|
-
opts.on("--max-threads NUM", "Maximum application threads per worker (`unlimited` for no limit; default:
|
|
272
|
+
opts.on("--max-threads NUM", "Maximum application threads per worker (`unlimited` for no limit; default: unlimited)") do |num|
|
|
263
273
|
@options[:max_threads] = num
|
|
264
274
|
end
|
|
265
275
|
|
data/lib/raptor/cluster.rb
CHANGED
|
@@ -126,7 +126,7 @@ module Raptor
|
|
|
126
126
|
# @option options [Boolean] :drain_accept_queue whether to drain the kernel accept queue on shutdown
|
|
127
127
|
# @option options [Integer] :workers number of worker processes
|
|
128
128
|
# @option options [Integer] :threads number of threads per worker process
|
|
129
|
-
# @option options [Integer, Float
|
|
129
|
+
# @option options [Integer, Float] :max_threads maximum number of threads per worker process, or `Float::INFINITY` for no limit
|
|
130
130
|
# @option options [#call] :app pre-built Rack application
|
|
131
131
|
# @option options [String] :rackup path to Rack configuration file
|
|
132
132
|
# @option options [String, nil] :chdir directory to change to before loading the Rack application, or nil to leave the working directory unchanged
|
|
@@ -784,15 +784,17 @@ module Raptor
|
|
|
784
784
|
end
|
|
785
785
|
end
|
|
786
786
|
|
|
787
|
-
http2_ractor_pool =
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
787
|
+
http2_ractor_pool = if @binder.http2?
|
|
788
|
+
RactorPool.new(
|
|
789
|
+
size: @http2_ractor_count,
|
|
790
|
+
worker: http2.parser_worker,
|
|
791
|
+
name: "HTTP/2"
|
|
792
|
+
) do |parsed_result|
|
|
793
|
+
begin
|
|
794
|
+
http2.handle_parsed_request(parsed_result, reactor, thread_pool)
|
|
795
|
+
rescue => error
|
|
796
|
+
Log.rescued_error(error)
|
|
797
|
+
end
|
|
796
798
|
end
|
|
797
799
|
end
|
|
798
800
|
|
|
@@ -871,7 +873,7 @@ module Raptor
|
|
|
871
873
|
reactor.shutdown
|
|
872
874
|
reactor_thread.join
|
|
873
875
|
http1_ractor_pool.shutdown
|
|
874
|
-
http2_ractor_pool
|
|
876
|
+
http2_ractor_pool&.shutdown
|
|
875
877
|
http1.shutdown
|
|
876
878
|
drain_thread_pool(thread_pool)
|
|
877
879
|
stats_thread.join
|
|
@@ -979,8 +981,10 @@ module Raptor
|
|
|
979
981
|
Log.info "│ ├─ 1 server thread"
|
|
980
982
|
Log.info "│ ├─ 1 reactor thread"
|
|
981
983
|
Log.info "│ ├─ #{@http1_ractor_count} HTTP/1.1 pipeline ractor#{"s" if @http1_ractor_count > 1}"
|
|
982
|
-
|
|
983
|
-
Log.info "│ ├─ 2 pipeline
|
|
984
|
+
http2_enabled = @binder.http2?
|
|
985
|
+
Log.info "│ ├─ #{@http2_ractor_count} HTTP/2 pipeline ractor#{"s" if @http2_ractor_count > 1}" if http2_enabled
|
|
986
|
+
collector_count = http2_enabled ? 2 : 1
|
|
987
|
+
Log.info "│ ├─ #{collector_count} pipeline collector thread#{"s" if collector_count > 1}"
|
|
984
988
|
thread_limit = if @max_thread_count == Float::INFINITY
|
|
985
989
|
" (scaling, no limit)"
|
|
986
990
|
elsif @max_thread_count
|
data/lib/raptor/reactor.rb
CHANGED
|
@@ -71,7 +71,7 @@ module Raptor
|
|
|
71
71
|
# Creates a new Reactor instance.
|
|
72
72
|
#
|
|
73
73
|
# @param http1_ractor_pool [RactorPool] ractor pool for HTTP/1.x parsing
|
|
74
|
-
# @param http2_ractor_pool [RactorPool] ractor pool for HTTP/2 parsing
|
|
74
|
+
# @param http2_ractor_pool [RactorPool, nil] ractor pool for HTTP/2 parsing, or nil when no listener supports HTTP/2
|
|
75
75
|
# @param thread_pool [AtomicThreadPool] thread pool for application processing
|
|
76
76
|
# @param connection_options [Hash] per-connection timeout configuration
|
|
77
77
|
# @option connection_options [Integer] :first_data_timeout timeout for initial data
|
data/lib/raptor/version.rb
CHANGED
|
@@ -81,6 +81,13 @@ module Raptor
|
|
|
81
81
|
# @rbs () -> Integer
|
|
82
82
|
def server_port: () -> Integer
|
|
83
83
|
|
|
84
|
+
# Returns whether any listener can negotiate HTTP/2.
|
|
85
|
+
#
|
|
86
|
+
# @return [Boolean]
|
|
87
|
+
#
|
|
88
|
+
# @rbs () -> bool
|
|
89
|
+
def http2?: () -> bool
|
|
90
|
+
|
|
84
91
|
# Closes all listening sockets.
|
|
85
92
|
#
|
|
86
93
|
# @return [void]
|
|
@@ -46,12 +46,14 @@ module Raptor
|
|
|
46
46
|
|
|
47
47
|
# Parses a maximum thread count from a CLI, config, or Rack handler value.
|
|
48
48
|
#
|
|
49
|
-
# @param value [Integer, Float, String
|
|
50
|
-
# @
|
|
51
|
-
#
|
|
52
|
-
#
|
|
53
|
-
# @
|
|
54
|
-
|
|
49
|
+
# @param value [Integer, Float, String] maximum thread count
|
|
50
|
+
# @param threads [Integer] baseline thread count
|
|
51
|
+
# @return [Integer, Float] parsed thread count, or `Float::INFINITY` for
|
|
52
|
+
# `"unlimited"`
|
|
53
|
+
# @raise [ArgumentError] if the maximum is nil or less than the baseline
|
|
54
|
+
#
|
|
55
|
+
# @rbs (Integer | Float | String value, threads: Integer) -> (Integer | Float)
|
|
56
|
+
def self.parse_max_threads: (Integer | Float | String value, threads: Integer) -> (Integer | Float)
|
|
55
57
|
|
|
56
58
|
@parser: OptionParser
|
|
57
59
|
|
|
@@ -150,7 +150,7 @@ module Raptor
|
|
|
150
150
|
# @option options [Boolean] :drain_accept_queue whether to drain the kernel accept queue on shutdown
|
|
151
151
|
# @option options [Integer] :workers number of worker processes
|
|
152
152
|
# @option options [Integer] :threads number of threads per worker process
|
|
153
|
-
# @option options [Integer, Float
|
|
153
|
+
# @option options [Integer, Float] :max_threads maximum number of threads per worker process, or `Float::INFINITY` for no limit
|
|
154
154
|
# @option options [#call] :app pre-built Rack application
|
|
155
155
|
# @option options [String] :rackup path to Rack configuration file
|
|
156
156
|
# @option options [String, nil] :chdir directory to change to before loading the Rack application, or nil to leave the working directory unchanged
|
|
@@ -73,7 +73,7 @@ module Raptor
|
|
|
73
73
|
# Creates a new Reactor instance.
|
|
74
74
|
#
|
|
75
75
|
# @param http1_ractor_pool [RactorPool] ractor pool for HTTP/1.x parsing
|
|
76
|
-
# @param http2_ractor_pool [RactorPool] ractor pool for HTTP/2 parsing
|
|
76
|
+
# @param http2_ractor_pool [RactorPool, nil] ractor pool for HTTP/2 parsing, or nil when no listener supports HTTP/2
|
|
77
77
|
# @param thread_pool [AtomicThreadPool] thread pool for application processing
|
|
78
78
|
# @param connection_options [Hash] per-connection timeout configuration
|
|
79
79
|
# @option connection_options [Integer] :first_data_timeout timeout for initial data
|