raptor 0.12.0 → 0.13.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.
@@ -1,30 +1,9 @@
1
1
  # Generated from lib/raptor/binder.rb with RBS::Inline
2
2
 
3
3
  module Raptor
4
- # Manages binding to network addresses and creating listening sockets.
5
- #
6
- # Binder handles parsing URI bind specifications, creating TCP, Unix, and SSL
7
- # server sockets, and managing socket options for optimal performance. It
8
- # supports binding to multiple addresses simultaneously.
9
- #
10
- # @example TCP binding
11
- # binder = Binder.new(["tcp://0.0.0.0:3000", "tcp://[::1]:3000"])
12
- # puts binder.addresses #=> ["0.0.0.0:3000", "[::1]:3000"]
13
- # binder.close
14
- #
15
- # @example Unix socket binding
16
- # binder = Binder.new(["unix:///tmp/raptor.sock"])
17
- # puts binder.addresses #=> ["/tmp/raptor.sock"]
18
- # binder.close
19
- #
20
- # @example SSL binding
21
- # binder = Binder.new(["ssl://0.0.0.0:443?cert=/path/to.crt&key=/path/to.key"])
22
- # puts binder.addresses #=> ["ssl://0.0.0.0:443"]
23
- # binder.close
24
- #
25
- # @example Localhost binding
26
- # binder = Binder.new(["tcp://localhost:8080"])
27
- # # Binds to both IPv4 and IPv6 loopback addresses
4
+ # Binds `tcp://`, `unix://`, and `ssl://` URIs to listening sockets and
5
+ # holds them for the server. Reconstructs listeners from inherited file
6
+ # descriptors when provided (systemd socket activation, hot restart).
28
7
  class Binder
29
8
  SOCKET_BACKLOG: ::Integer
30
9
 
@@ -33,11 +12,8 @@ module Raptor
33
12
  def initialize: (String scheme) -> void
34
13
  end
35
14
 
36
- # Wraps a TCPServer with an SSL context for accepting SSL connections.
37
- #
38
- # Holds both the underlying TCP server and the SSL context together so
39
- # the server thread can accept a TCP connection and then perform the SSL
40
- # handshake in a single coordinated step.
15
+ # Pairs a TCPServer with the SSL context to use for accepted
16
+ # connections.
41
17
  class SslListener < Data
42
18
  attr_reader tcp_server(): untyped
43
19
 
@@ -61,28 +37,24 @@ module Raptor
61
37
 
62
38
  @bind_uris: Array[String]
63
39
 
64
- # Array of bind URIs.
40
+ # Returns the array of bind URIs.
65
41
  #
66
- # @return [Array<String>] the bind URIs
42
+ # @return [Array<String>]
67
43
  attr_reader bind_uris: untyped
68
44
 
69
- # Kernel listen() queue depth for TCP/SSL listeners.
45
+ # Returns the kernel `listen()` queue depth for TCP/SSL listeners.
70
46
  #
71
- # @return [Integer] the socket backlog
47
+ # @return [Integer]
72
48
  attr_reader socket_backlog: untyped
73
49
 
74
- # Array of listening sockets.
50
+ # Returns the array of listening sockets.
75
51
  #
76
- # @return [Array<TCPServer, UNIXServer, SslListener>] the server sockets
52
+ # @return [Array<TCPServer, UNIXServer, SslListener>]
77
53
  attr_reader listeners: untyped
78
54
 
79
- # Creates a new Binder with the specified bind URIs.
80
- #
81
- # Parses the provided bind URIs and creates listening sockets for each one.
82
- # Supports tcp://, unix://, and ssl:// schemes. Localhost is expanded to
83
- # all available loopback addresses (both IPv4 and IPv6). When `inherited_fds`
84
- # supplies file descriptors for a URI, the listener is reconstructed from
85
- # those FDs instead of binding fresh.
55
+ # Creates a new Binder and binds each URI. `localhost` expands to both
56
+ # IPv4 and IPv6 loopback; when `inherited_fds` supplies file descriptors
57
+ # for a URI the listener is rebuilt from those instead of binding fresh.
86
58
  #
87
59
  # @param bind_uris [Array<String>] array of URI strings to bind to
88
60
  # @param socket_backlog [Integer] kernel listen() queue depth for TCP/SSL listeners
@@ -90,31 +62,21 @@ module Raptor
90
62
  # @return [void]
91
63
  # @raise [UnknownBindSchemeError] if a URI has an unsupported scheme
92
64
  #
93
- # @example
94
- # binder = Binder.new(["tcp://0.0.0.0:3000", "unix:///tmp/raptor.sock"])
95
- #
96
65
  # @rbs (Array[String] bind_uris, ?socket_backlog: Integer, ?inherited_fds: Hash[String, Array[Integer]]) -> void
97
66
  def initialize: (Array[String] bind_uris, ?socket_backlog: Integer, ?inherited_fds: Hash[String, Array[Integer]]) -> void
98
67
 
99
- # Returns the bound addresses as strings.
100
- #
101
- # TCP listeners are returned as "host:port", Unix listeners as the socket
102
- # path, and SSL listeners as "ssl://host:port".
68
+ # Returns the bound addresses as strings: TCP as `host:port`, Unix as
69
+ # the socket path, SSL as `ssl://host:port`.
103
70
  #
104
- # @return [Array<String>] address strings for each bound listener
105
- #
106
- # @example
107
- # binder.addresses #=> ["127.0.0.1:3000", "/tmp/raptor.sock", "ssl://0.0.0.0:443"]
71
+ # @return [Array<String>]
108
72
  #
109
73
  # @rbs () -> Array[String]
110
74
  def addresses: () -> Array[String]
111
75
 
112
- # Returns the port number of the first TCP or SSL listener.
113
- #
114
- # Used to populate SERVER_PORT in the Rack environment. Returns 0
115
- # if no TCP or SSL listener is configured (e.g., Unix socket only).
76
+ # Returns the port of the first TCP or SSL listener, or 0 when none
77
+ # is configured.
116
78
  #
117
- # @return [Integer] the port number, or 0 if no TCP listener exists
79
+ # @return [Integer]
118
80
  #
119
81
  # @rbs () -> Integer
120
82
  def server_port: () -> Integer
@@ -126,9 +88,7 @@ module Raptor
126
88
  # @rbs () -> void
127
89
  def close: () -> void
128
90
 
129
- # Returns the file descriptors of every listener, grouped by the bind URI
130
- # they were created from. The result is the payload to hand to a successor
131
- # process via the `inherited_fds:` constructor argument.
91
+ # Returns the file descriptors of every listener, grouped by bind URI.
132
92
  #
133
93
  # @return [Hash{String => Array<Integer>}]
134
94
  #
@@ -154,25 +114,25 @@ module Raptor
154
114
  # @rbs () -> void
155
115
  def parse: () -> void
156
116
 
157
- # Creates fresh listeners for the given bind URI.
117
+ # Creates fresh listeners for the given URI.
158
118
  #
159
- # @param bind_uri [String] the URI to bind
119
+ # @param uri [URI] the parsed bind URI
160
120
  # @return [Array<TCPServer, UNIXServer, SslListener>]
161
121
  # @raise [UnknownBindSchemeError] if the URI scheme is not supported
162
122
  #
163
- # @rbs (String bind_uri) -> Array[TCPServer | UNIXServer | SslListener]
164
- def create_listeners: (String bind_uri) -> Array[TCPServer | UNIXServer | SslListener]
123
+ # @rbs (URI::Generic uri) -> Array[TCPServer | UNIXServer | SslListener]
124
+ def create_listeners: (URI::Generic uri) -> Array[TCPServer | UNIXServer | SslListener]
165
125
 
166
- # Reconstructs listeners for the given bind URI from inherited file
126
+ # Reconstructs listeners for the given URI from inherited file
167
127
  # descriptors.
168
128
  #
169
- # @param bind_uri [String] the URI the FDs were bound to
129
+ # @param uri [URI] the parsed bind URI the FDs were bound to
170
130
  # @param filenos [Array<Integer>] file descriptors to wrap
171
131
  # @return [Array<TCPServer, UNIXServer, SslListener>]
172
132
  # @raise [UnknownBindSchemeError] if the URI scheme is not supported
173
133
  #
174
- # @rbs (String bind_uri, Array[Integer] filenos) -> Array[TCPServer | UNIXServer | SslListener]
175
- def restore_listeners: (String bind_uri, Array[Integer] filenos) -> Array[TCPServer | UNIXServer | SslListener]
134
+ # @rbs (URI::Generic uri, Array[Integer] filenos) -> Array[TCPServer | UNIXServer | SslListener]
135
+ def restore_listeners: (URI::Generic uri, Array[Integer] filenos) -> Array[TCPServer | UNIXServer | SslListener]
176
136
 
177
137
  # Creates TCP server sockets for the given host and port.
178
138
  #
@@ -183,11 +143,9 @@ module Raptor
183
143
  # @rbs (String? host, Integer? port) -> Array[TCPServer]
184
144
  def create_tcp_listeners: (String? host, Integer? port) -> Array[TCPServer]
185
145
 
186
- # Creates a Unix domain server socket at the given path.
187
- #
188
- # Removes stale socket files left by crashed processes (when the socket
189
- # is not currently in use). Registers an at_exit hook to clean up the
190
- # socket file on normal process exit.
146
+ # Creates a Unix domain server socket at the given path. Removes stale
147
+ # socket files left by crashed processes, and cleans the file up on
148
+ # the master's clean exit.
191
149
  #
192
150
  # @param path [String] filesystem path for the Unix socket
193
151
  # @return [Array<UNIXServer>] array containing the created Unix server socket
@@ -206,15 +164,11 @@ module Raptor
206
164
  # @rbs (String path) -> void
207
165
  def register_unix_socket_cleanup: (String path) -> void
208
166
 
209
- # Creates SSL server sockets for the given host, port, and SSL parameters.
210
- #
211
- # Wraps each TCP listener with an SSL context to produce SslListener objects.
212
- # The ssl_params hash must include "cert" and "key" entries pointing to the
213
- # certificate and private key files respectively.
167
+ # Creates SSL server sockets for the given host and port.
214
168
  #
215
169
  # @param host [String, nil] hostname or IP address to bind to
216
170
  # @param port [Integer, nil] port number to bind to
217
- # @param ssl_params [Hash<String, String>] SSL options ("cert" and "key" paths)
171
+ # @param ssl_params [Hash<String, String>] SSL options (`cert` and `key` file paths)
218
172
  # @return [Array<SslListener>] array containing the created SSL listener(s)
219
173
  #
220
174
  # @rbs (String? host, Integer? port, Hash[String, String] ssl_params) -> Array[SslListener]
@@ -24,11 +24,9 @@ module Raptor
24
24
 
25
25
  DEFAULT_CONFIG_PATHS: untyped
26
26
 
27
- # Loads a configuration file and returns the hash it evaluates to.
28
- #
29
- # The file is evaluated at the top level so constants like `Raptor::*` resolve
30
- # the same as in a regular Ruby script. The final expression must be a Hash
31
- # of cluster options (the same keys accepted by {Raptor::Cluster#initialize}).
27
+ # Loads a Ruby config file and returns the options hash it evaluates
28
+ # to. Evaluated at the top level so `Raptor::*` constants resolve the
29
+ # same as in a regular script.
32
30
  #
33
31
  # @param path [String] path to a Ruby file that evaluates to a Hash
34
32
  # @return [Hash{Symbol => untyped}] cluster options
@@ -40,9 +38,6 @@ module Raptor
40
38
  # Returns the first existing path in {DEFAULT_CONFIG_PATHS} resolved
41
39
  # against `root`, or nil if none exist.
42
40
  #
43
- # Used to pick up a project-local config file when no `-c`/`--config`
44
- # flag was supplied.
45
- #
46
41
  # @param root [String] directory to resolve the default paths against
47
42
  # @return [String, nil] the config path, or nil if no default file exists
48
43
  #
@@ -55,22 +50,14 @@ module Raptor
55
50
 
56
51
  @parser: OptionParser
57
52
 
58
- # Creates a new CLI instance and parses command-line arguments.
59
- #
60
- # Parses the provided command-line arguments and configures the server
61
- # options accordingly. A rackup file can be provided as the first
62
- # positional argument (defaults to config.ru).
53
+ # Creates a new CLI instance from `argv`. A rackup file may be given
54
+ # as the first positional argument; every other value is parsed as a
55
+ # flag.
63
56
  #
64
57
  # @param argv [Array<String>] command-line arguments to parse
65
58
  # @return [void]
66
59
  # @raise [OptionParser::ParseError] if invalid options are provided
67
60
  #
68
- # @example With rackup file
69
- # cli = CLI.new(["my_app.ru", "-w", "4"])
70
- #
71
- # @example With options only
72
- # cli = CLI.new(["-t", "8", "-r", "2"])
73
- #
74
61
  # @rbs (Array[String] argv) -> void
75
62
  def initialize: (Array[String] argv) -> void
76
63
 
@@ -90,12 +77,9 @@ module Raptor
90
77
  # @rbs () -> void
91
78
  def run_stats: () -> void
92
79
 
93
- # Scans argv for a `-c`/`--config` flag and returns the configured path.
94
- #
95
- # The pre-scan runs before the main OptionParser pass so the config file
96
- # can be applied as a base layer that CLI args then override. All four
97
- # OptionParser-accepted forms (`-c PATH`, `-cPATH`, `--config PATH`,
98
- # `--config=PATH`) are recognized.
80
+ # Returns the path from a `-c`/`--config` flag in `argv`, recognising
81
+ # all four OptionParser-accepted forms (`-c PATH`, `-cPATH`,
82
+ # `--config PATH`, `--config=PATH`).
99
83
  #
100
84
  # @param argv [Array<String>] command-line arguments to scan
101
85
  # @return [String, nil] the config path, or nil if no flag was supplied
@@ -1,38 +1,14 @@
1
1
  # Generated from lib/raptor/cluster.rb with RBS::Inline
2
2
 
3
3
  module Raptor
4
- # Multi-process web server cluster with advanced concurrency architecture.
5
- #
6
- # Cluster manages multiple worker processes, each running a complete server
7
- # stack including a ractor pool for HTTP parsing, a thread pool for
8
- # application processing, plus dedicated reactor and server threads. It
9
- # handles process forking, signal management, graceful shutdown, and
10
- # automatic worker restart when a worker process unexpectedly exits.
11
- #
12
- # The architecture provides horizontal scaling through processes while
13
- # maintaining efficient I/O and CPU utilization within each process
14
- # through the combination of ractor-based parsing and thread pools on
15
- # top of NIO reactors.
16
- #
17
- # Flow per worker process:
18
- # 1. Server continuously accepts connections but skips acceptance when backlog is high
19
- # 2. Reactor manages I/O multiplexing and provides backlog metrics for load control
20
- # 3. Ractor pool handles CPU-intensive HTTP parsing in parallel
21
- # 4. Thread pool processes Rack applications and handles response writing
22
- # 5. Natural load balancing occurs through backpressure-based acceptance control
23
- #
24
- # @example Basic usage
25
- # options = {
26
- # workers: 4, ractors: 2, threads: 8,
27
- # binds: ["tcp://0.0.0.0:3000"],
28
- # rackup: "config.ru",
29
- # connection: { first_data_timeout: 30, chunk_data_timeout: 10 }
30
- # }
31
- # Cluster.run(options)
4
+ # Forks and supervises worker processes. Handles graceful shutdown on
5
+ # `INT` and `TERM`, phased restart on `USR1`, hot restart on `USR2`,
6
+ # and (on Linux) refork on `URG`. Restarts workers that exit
7
+ # unexpectedly or stop checking in.
32
8
  class Cluster
33
9
  INHERITED_FDS_ENV: ::String
34
10
 
35
- # Convenience method to create and run a cluster with the given options.
11
+ # Creates and runs a cluster with the given options.
36
12
  #
37
13
  # @param options [Hash] cluster configuration options
38
14
  # @return [void]
@@ -134,11 +110,7 @@ module Raptor
134
110
 
135
111
  @drain_accept_queue: bool
136
112
 
137
- # Creates a new Cluster with the specified configuration.
138
- #
139
- # Initializes the cluster with worker, ractor, and thread counts,
140
- # sets up network binding, loads the Rack application, and prepares
141
- # for multi-process operation.
113
+ # Creates a new Cluster with the given options.
142
114
  #
143
115
  # @param options [Hash] cluster configuration options
144
116
  # @option options [Array<String>] :binds array of bind URIs
@@ -176,20 +148,7 @@ module Raptor
176
148
  # @rbs (Hash[Symbol, untyped] options) -> void
177
149
  def initialize: (Hash[Symbol, untyped] options) -> void
178
150
 
179
- # Starts the multi-process cluster and manages worker processes.
180
- #
181
- # Forks the configured number of worker processes and monitors them,
182
- # restarting any that exit unexpectedly or stop checking in. Handles
183
- # graceful shutdown via INT or TERM signals, phased restart via USR1,
184
- # and hot restart via USR2.
185
- #
186
- # Each worker process includes:
187
- # - 1 server thread (continuously accepts connections with backpressure control)
188
- # - 1 reactor thread (I/O multiplexing, timeout handling, backlog monitoring)
189
- # - N pipeline ractors (parallel HTTP parsing)
190
- # - 1 pipeline collector thread (coordinates parsing results)
191
- # - M worker threads (Rack application processing and response writing)
192
- # - 1 stats thread (writes per-worker metrics to shared memory every second)
151
+ # Runs the cluster until a graceful shutdown is signalled.
193
152
  #
194
153
  # @return [void]
195
154
  #
@@ -199,7 +158,8 @@ module Raptor
199
158
  # Returns stats for all worker processes.
200
159
  #
201
160
  # @return [Array<Hash>] array of per-worker stat hashes, each containing
202
- # :pid, :requests, :backlog, :started_at, :last_checkin, and :booted
161
+ # :pid, :index, :phase, :requests, :backlog, :busy_threads,
162
+ # :thread_capacity, :started_at, :last_checkin, and :booted
203
163
  #
204
164
  # @rbs () -> Array[Hash[Symbol, untyped]]
205
165
  def stats: () -> Array[Hash[Symbol, untyped]]
@@ -208,8 +168,7 @@ module Raptor
208
168
 
209
169
  # Returns the inherited-FDs hash for a systemd socket-activation handoff,
210
170
  # pairing each bind URI with the FD systemd passed at the same index.
211
- # The activation is skipped (with a warning) when the FD count doesn't
212
- # match the number of bind URIs.
171
+ # Returns an empty hash when the FD count doesn't match the bind count.
213
172
  #
214
173
  # @param bind_uris [Array<String>] the configured bind URIs
215
174
  # @param filenos [Array<Integer>] file descriptors passed by systemd
@@ -51,6 +51,16 @@ module Raptor
51
51
  # @rbs (TCPSocket socket, Array[String] strings, ?timeout: Integer) -> void
52
52
  def self.socket_writev: (TCPSocket socket, Array[String] strings, ?timeout: Integer) -> void
53
53
 
54
+ # Returns a Ractor-safe proc that routes each pipeline task to the
55
+ # HTTP/1.x or HTTP/2 handler based on the state hash's `:protocol` key.
56
+ #
57
+ # @param env_template [Hash] the Rack env template to seed each HTTP/1.x request with
58
+ # @param max_body_size [Integer, nil] byte limit for HTTP/1.x request bodies, or nil for no limit
59
+ # @return [Proc]
60
+ #
61
+ # @rbs (Hash[String, untyped] env_template, Integer? max_body_size) -> ^(Hash[Symbol, untyped]) -> Hash[Symbol, untyped]
62
+ def self.parser_worker: (Hash[String, untyped] env_template, Integer? max_body_size) -> ^(Hash[Symbol, untyped]) -> Hash[Symbol, untyped]
63
+
54
64
  # Writes a Common Log Format entry to `io`. Write failures are silently
55
65
  # ignored.
56
66
  #