raptor 0.11.0 → 0.12.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.
@@ -40,57 +40,85 @@ module Raptor
40
40
  # @rbs (Hash[Symbol, untyped] options) -> void
41
41
  def self.run: (Hash[Symbol, untyped] options) -> void
42
42
 
43
- @http2_options: Hash[Symbol, untyped]
43
+ @bpf_active: bool
44
44
 
45
- @worker_boot_timeout: Integer
45
+ @server_port: Integer
46
46
 
47
- @worker_timeout: Integer
47
+ @binder: Binder
48
48
 
49
- @worker_drain_timeout: Integer
49
+ @on_error: ^(Hash[String, untyped]?, Exception) -> void | nil
50
50
 
51
- @worker_shutdown_timeout: Integer
51
+ @launch_argv: Array[String]?
52
52
 
53
- @stats_file: String?
53
+ @launch_command: String?
54
54
 
55
- @pid_file: String?
55
+ @access_log_io: IO?
56
56
 
57
- @stdout_file: String?
57
+ @access_log_file: String?
58
58
 
59
59
  @stderr_file: String?
60
60
 
61
- @access_log_file: String?
61
+ @stdout_file: String?
62
62
 
63
- @access_log_io: IO?
63
+ @pid_file: String?
64
64
 
65
- @launch_command: String?
65
+ @stats_file: String?
66
66
 
67
- @launch_argv: Array[String]?
67
+ @before_refork: Array[Proc]
68
68
 
69
- @on_error: ^(Hash[String, untyped]?, Exception) -> void | nil
69
+ @before_worker_shutdown: Array[Proc]
70
70
 
71
- @binder: Binder
71
+ @before_worker_boot: Array[Proc]
72
72
 
73
- @server_port: Integer
73
+ @before_fork: Array[Proc]
74
74
 
75
- @app: untyped
75
+ @worker_shutdown_timeout: Integer
76
76
 
77
- @shutdown: bool
77
+ @worker_drain_timeout: Integer
78
78
 
79
- @workers: Hash[Integer, Integer]
79
+ @worker_timeout: Integer
80
80
 
81
- @timed_out: Set[Integer]
81
+ @worker_boot_timeout: Integer
82
82
 
83
- @stats: Stats
83
+ @resp_w: IO?
84
84
 
85
- @phase: Integer
85
+ @resp_r: IO?
86
86
 
87
- @phased_restart_requested: bool
87
+ @fork_w: IO?
88
88
 
89
- @phased_restarting: bool
89
+ @fork_r: IO?
90
+
91
+ @seed_vacated_index: Integer?
92
+
93
+ @seed_ready: bool
94
+
95
+ @seed_pid: Integer?
96
+
97
+ @refork_threshold_idx: Integer
98
+
99
+ @refork_requested: bool
100
+
101
+ @refork_thresholds: Array[Integer]
90
102
 
91
103
  @hot_restart_requested: bool
92
104
 
93
- @bpf_active: bool
105
+ @phased_restarting: bool
106
+
107
+ @phased_restart_requested: bool
108
+
109
+ @phase: Integer
110
+
111
+ @stats: Stats
112
+
113
+ @timed_out: Set[Integer]
114
+
115
+ @workers: Hash[Integer, Integer]
116
+
117
+ @shutdown: bool
118
+
119
+ @app: untyped
120
+
121
+ @http2_options: Hash[Symbol, untyped]
94
122
 
95
123
  @http1_options: Hash[Symbol, untyped]
96
124
 
@@ -130,6 +158,11 @@ module Raptor
130
158
  # @option options [Integer] :worker_timeout seconds to wait for a booted worker to check in before killing it
131
159
  # @option options [Integer] :worker_drain_timeout seconds a worker waits for in-flight requests during shutdown before force-killing app threads
132
160
  # @option options [Integer] :worker_shutdown_timeout seconds to wait for graceful worker exit before force-killing
161
+ # @option options [Integer, Array<Integer>, nil] :refork_after request-count threshold(s) at which a warm worker is promoted to a fork source for phased refork; nil or 0 disables. Requires `PR_SET_CHILD_SUBREAPER` (Linux)
162
+ # @option options [Array<Proc>] :before_fork procs called in the master before every worker fork
163
+ # @option options [Array<Proc>] :before_worker_boot procs called in each worker before it begins serving
164
+ # @option options [Array<Proc>] :before_worker_shutdown procs called in each worker before its graceful shutdown
165
+ # @option options [Array<Proc>] :before_refork procs called in a worker before it transitions to a seed
133
166
  # @option options [String, nil] :stats_file path to write per-worker stats JSON, or nil to disable
134
167
  # @option options [String, nil] :pid_file path to write the master PID to, or nil to disable
135
168
  # @option options [String, nil] :stdout_file path to redirect stdout to, reopened on SIGHUP, or nil to disable
@@ -185,8 +218,18 @@ module Raptor
185
218
  # @rbs (Array[String] bind_uris, Array[Integer] filenos) -> Hash[String, Array[Integer]]
186
219
  def pair_systemd_fds: (Array[String] bind_uris, Array[Integer] filenos) -> Hash[String, Array[Integer]]
187
220
 
188
- # Forks a new worker process and registers it at the given index.
189
- # The worker inherits the cluster's current phase.
221
+ # Normalises the `refork_after` option into a sorted array of positive
222
+ # thresholds. Accepts nil, 0, an Integer, or an Array<Integer>; anything
223
+ # else falls back to an empty array (feature disabled).
224
+ #
225
+ # @param value [Integer, Array<Integer>, nil] the raw option value
226
+ # @return [Array<Integer>]
227
+ #
228
+ # @rbs (untyped value) -> Array[Integer]
229
+ def normalize_refork_thresholds: (untyped value) -> Array[Integer]
230
+
231
+ # Forks a new worker process and registers it at the given index,
232
+ # forking from the seed when one is active and off the master otherwise.
190
233
  #
191
234
  # @param index [Integer] slot index for this worker in the stats region
192
235
  # @return [void]
@@ -194,16 +237,87 @@ module Raptor
194
237
  # @rbs (Integer index) -> void
195
238
  def spawn_worker: (Integer index) -> void
196
239
 
240
+ # Asks the seed to fork a new worker at the given index, returning the
241
+ # child pid, or nil when the seed doesn't respond in time.
242
+ #
243
+ # @param index [Integer] slot index for the new worker
244
+ # @return [Integer, nil] the forked worker's pid, or nil on failure
245
+ #
246
+ # @rbs (Integer index) -> Integer?
247
+ def spawn_worker_via_seed: (Integer index) -> Integer?
248
+
249
+ # Checks whether a process with the given pid is currently alive.
250
+ #
251
+ # @param pid [Integer] the pid to probe
252
+ # @return [Boolean] true if the process exists
253
+ #
254
+ # @rbs (Integer pid) -> bool
255
+ def pid_alive?: (Integer pid) -> bool
256
+
197
257
  # Reaps any worker processes that have exited, respawning each one
198
258
  # unless the cluster is shutting down.
199
259
  #
200
- # @return [Symbol] :no_children when there are no remaining children, otherwise :reaped
260
+ # @return [Symbol] :no_children when nothing is left to supervise, otherwise :reaped
201
261
  #
202
262
  # @rbs () -> Symbol
203
263
  def reap_workers: () -> Symbol
204
264
 
205
- # Stops every worker, escalating from TERM to KILL if any fail to
206
- # exit within `worker_shutdown_timeout`.
265
+ # Records a reaped pid, respawning its worker slot unless the cluster
266
+ # is shutting down. Clears the seed reference when the seed exits.
267
+ #
268
+ # @param pid [Integer] the reaped pid
269
+ # @param status [Process::Status] the exit status
270
+ # @return [void]
271
+ #
272
+ # @rbs (Integer pid, Process::Status status) -> void
273
+ def reap_pid: (Integer pid, Process::Status status) -> void
274
+
275
+ # Promotes the most-experienced worker to a seed and starts a phased
276
+ # refork when the next `refork_after` threshold is crossed or a manual
277
+ # refork was requested via `SIGURG`.
278
+ #
279
+ # @return [void]
280
+ #
281
+ # @rbs () -> void
282
+ def check_refork_trigger: () -> void
283
+
284
+ # Picks the most-experienced booted worker in the current phase,
285
+ # returning its slot index and its request count. Returns nil when
286
+ # no worker qualifies.
287
+ #
288
+ # @return [Array<Integer>, nil]
289
+ #
290
+ # @rbs () -> Array[Integer]?
291
+ def pick_refork_candidate: () -> Array[Integer]?
292
+
293
+ # Retires the current seed and promotes the given worker into its place,
294
+ # queueing a phased refork for the remaining workers.
295
+ #
296
+ # @param index [Integer] slot index of the worker to promote
297
+ # @return [void]
298
+ #
299
+ # @rbs (Integer index) -> void
300
+ def promote_worker_to_seed: (Integer index) -> void
301
+
302
+ # Terminates the currently-active seed process, if any, and waits for
303
+ # it to exit. Its seed-forked workers stay attached to the master and
304
+ # keep serving.
305
+ #
306
+ # @return [void]
307
+ #
308
+ # @rbs () -> void
309
+ def retire_current_seed: () -> void
310
+
311
+ # Records the seed's readiness when its ready marker has arrived.
312
+ # Non-blocking.
313
+ #
314
+ # @return [void]
315
+ #
316
+ # @rbs () -> void
317
+ def poll_seed_ready: () -> void
318
+
319
+ # Stops every worker (and the seed if one is active), escalating
320
+ # from TERM to KILL if any fail to exit within `worker_shutdown_timeout`.
207
321
  #
208
322
  # @return [void]
209
323
  #
@@ -229,6 +343,23 @@ module Raptor
229
343
  # @rbs () -> void
230
344
  def perform_phased_restart: () -> void
231
345
 
346
+ # Blocks until the freshly-promoted seed has signalled readiness,
347
+ # or times out and clears the seed reference. No-op when no seed is
348
+ # being promoted.
349
+ #
350
+ # @return [void]
351
+ #
352
+ # @rbs () -> void
353
+ def wait_for_seed_ready: () -> void
354
+
355
+ # Spawns a replacement worker for the slot the seed vacated when
356
+ # it was promoted, returning the slot index it filled.
357
+ #
358
+ # @return [Integer, nil] the filled slot index, or nil if none was vacated
359
+ #
360
+ # @rbs () -> Integer?
361
+ def fill_vacated_seed_slot: () -> Integer?
362
+
232
363
  # Re-execs the master process with a fresh boot of the same Raptor
233
364
  # invocation, handing the new master its listening sockets so accepted
234
365
  # connections continue to be served across the swap.
@@ -238,11 +369,10 @@ module Raptor
238
369
  # @rbs () -> void
239
370
  def perform_hot_restart: () -> void
240
371
 
241
- # Runs the full server stack inside a worker process.
242
- #
243
- # Sets up and coordinates the reactor, server, ractor pool, thread pool,
244
- # and stats thread, running until a shutdown signal is received or a
245
- # critical component fails.
372
+ # Runs a worker process's full server stack until a shutdown signal is
373
+ # received or a critical component fails. On `SIGURG` the worker drains
374
+ # and transitions into a seed loop that forks replacement workers on
375
+ # master's request.
246
376
  #
247
377
  # @param index [Integer] slot index for this worker in the stats region
248
378
  # @param phase [Integer] the cluster phase this worker was forked at
@@ -251,6 +381,15 @@ module Raptor
251
381
  # @rbs (Integer index, Integer phase) -> void
252
382
  def run_worker: (Integer index, Integer phase) -> void
253
383
 
384
+ # Runs the seed's fork loop, forking a replacement worker for each
385
+ # slot index the master asks for.
386
+ #
387
+ # @param index [Integer] the seed's original slot index
388
+ # @return [void]
389
+ #
390
+ # @rbs (Integer index) -> void
391
+ def run_seed_loop: (Integer index) -> void
392
+
254
393
  # Shuts down the worker's application thread pool, force-killing the
255
394
  # underlying threads if in-flight requests have not finished within
256
395
  # `worker_drain_timeout` seconds.
@@ -52,5 +52,14 @@ module Raptor
52
52
  #
53
53
  # @rbs (Integer backlog) -> void
54
54
  def self.update_load: (Integer backlog) -> void
55
+
56
+ # Marks a worker's slot as unavailable by parking its load at the
57
+ # sentinel maximum so the BPF program's least-loaded pick skips it.
58
+ #
59
+ # @param worker_index [Integer] slot index for the worker to mark
60
+ # @return [void]
61
+ #
62
+ # @rbs (Integer worker_index) -> void
63
+ def self.mark_unavailable: (Integer worker_index) -> void
55
64
  end
56
65
  end
@@ -82,11 +82,17 @@ module Raptor
82
82
  # @rbs () -> Thread
83
83
  def run: () -> Thread
84
84
 
85
- # Gracefully shuts down the server.
85
+ # Stops the accept loop and, when `drain_accept_queue` is enabled,
86
+ # dispatches every connection already in the kernel accept queue. Leaves
87
+ # the listening sockets open so they can be handed to replacement workers.
86
88
  #
87
- # Stops accepting new connections and closes all listening sockets. When
88
- # `drain_accept_queue` is enabled, dispatches every connection already in
89
- # the kernel accept queue before closing the listeners.
89
+ # @return [void]
90
+ #
91
+ # @rbs () -> void
92
+ def stop_accepting: () -> void
93
+
94
+ # Gracefully shuts down the server, stopping the accept loop and closing
95
+ # all listening sockets.
90
96
  #
91
97
  # @return [void]
92
98
  #
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.11.0
4
+ version: 0.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joshua Young