puma 8.1.0-java → 8.1.1-java

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.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +10 -0
  3. data/README.md +16 -381
  4. data/docs/binding.md +135 -0
  5. data/docs/cluster_mode.md +241 -0
  6. data/docs/configuration.md +78 -0
  7. data/docs/{stats.md → control_server.md} +23 -3
  8. data/docs/{deployment.md → deployment/README.md} +20 -4
  9. data/docs/{kubernetes.md → deployment/kubernetes.md} +1 -1
  10. data/docs/plugins.md +61 -2
  11. data/docs/puma_support.md +15 -1
  12. data/docs/restart.md +5 -1
  13. data/docs/signals.md +2 -0
  14. data/docs/{5.0-Upgrade.md → upgrading/5.0-Upgrade.md} +3 -3
  15. data/docs/{6.0-Upgrade.md → upgrading/6.0-Upgrade.md} +2 -2
  16. data/docs/{7.0-Upgrade.md → upgrading/7.0-Upgrade.md} +2 -2
  17. data/docs/{8.0-Upgrade.md → upgrading/8.0-Upgrade.md} +2 -2
  18. data/lib/puma/cluster.rb +0 -1
  19. data/lib/puma/const.rb +1 -1
  20. data/lib/puma/minissl.rb +1 -4
  21. data/lib/puma/puma_http11.jar +0 -0
  22. metadata +17 -35
  23. data/docs/fork_worker.md +0 -71
  24. data/docs/grpc.md +0 -62
  25. data/docs/jungle/README.md +0 -9
  26. data/docs/testing_benchmarks_local_files.md +0 -150
  27. data/docs/testing_test_rackup_ci_files.md +0 -36
  28. data/ext/puma_http11/PumaHttp11Service.java +0 -17
  29. data/ext/puma_http11/extconf.rb +0 -67
  30. data/ext/puma_http11/http11_parser.c +0 -1061
  31. data/ext/puma_http11/http11_parser.h +0 -65
  32. data/ext/puma_http11/http11_parser.java.rl +0 -131
  33. data/ext/puma_http11/http11_parser.rl +0 -149
  34. data/ext/puma_http11/http11_parser_common.rl +0 -57
  35. data/ext/puma_http11/mini_ssl.c +0 -863
  36. data/ext/puma_http11/no_ssl/PumaHttp11Service.java +0 -15
  37. data/ext/puma_http11/org/jruby/puma/EnvKey.java +0 -241
  38. data/ext/puma_http11/org/jruby/puma/Http11.java +0 -321
  39. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +0 -441
  40. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +0 -519
  41. data/ext/puma_http11/puma_http11.c +0 -524
  42. data/tools/Dockerfile +0 -26
  43. data/tools/trickletest.rb +0 -44
  44. /data/docs/{nginx.md → deployment/nginx.md} +0 -0
  45. /data/docs/{jungle → deployment}/rc.d/README.md +0 -0
  46. /data/docs/{jungle → deployment}/rc.d/puma +0 -0
  47. /data/docs/{jungle → deployment}/rc.d/puma.conf +0 -0
  48. /data/docs/{systemd.md → deployment/systemd.md} +0 -0
@@ -0,0 +1,241 @@
1
+ # Cluster mode
2
+
3
+ Puma also offers "cluster mode". Cluster mode `fork`s workers from a master process. Each child process still has its own thread pool. You can tune the number of workers with the `-w` (or `--workers`) flag:
4
+
5
+ ```
6
+ $ puma -t 8:32 -w 3
7
+ ```
8
+
9
+ Or with the `WEB_CONCURRENCY` environment variable:
10
+
11
+ ```
12
+ $ WEB_CONCURRENCY=3 puma -t 8:32
13
+ ```
14
+
15
+ When using a config file, most applications can simply set `workers :auto` (requires the `concurrent-ruby` gem) to match the number of worker processes to the available processors:
16
+
17
+ ```ruby
18
+ # config/puma.rb
19
+ workers :auto
20
+ ```
21
+
22
+ See [`workers :auto` gotchas](../lib/puma/dsl.rb).
23
+
24
+ Note that threads are still used in cluster mode, and the `-t` thread flag setting is per worker, so `-w 2 -t 16:16` will spawn 32 threads in total, with 16 in each worker process.
25
+
26
+ If `workers` is set to `:auto`, or the `WEB_CONCURRENCY` environment variable is set to `"auto"`, and the `concurrent-ruby` gem is available in your application, Puma will set the worker process count to the result of [available processors](https://msp-greg.github.io/concurrent-ruby/Concurrent.html#available_processor_count-class_method).
27
+
28
+ For an in-depth discussion of the tradeoffs of thread and process count settings, [see our docs](deployment/README.md).
29
+
30
+ In cluster mode, Puma can "preload" your application. This loads all the application code *prior* to forking. Preloading reduces total memory usage of your application via an operating system feature called [copy-on-write](https://en.wikipedia.org/wiki/Copy-on-write).
31
+
32
+ If the number of workers is greater than 1 (and `--prune-bundler` has not been specified), preloading will be enabled by default. Otherwise, you can use the `--preload` flag from the command line:
33
+
34
+ ```
35
+ $ puma -w 3 --preload
36
+ ```
37
+
38
+ Or, if you're using a configuration file, you can use the `preload_app!` method:
39
+
40
+ ```ruby
41
+ # config/puma.rb
42
+ workers 3
43
+ preload_app!
44
+ ```
45
+
46
+ Preloading can’t be used with phased restart, since phased restart kills and restarts workers one-by-one, and preloading copies the code of master into the workers.
47
+
48
+ ## Cluster mode hooks
49
+
50
+ When using clustered mode, Puma's configuration DSL provides `before_fork`, `before_worker_boot`, and `after_worker_shutdown`
51
+ hooks to run code when the master process forks, the child workers are booted, and after each child worker exits respectively.
52
+
53
+ It is recommended to use these hooks with `preload_app!`, otherwise constants loaded by your
54
+ application (such as `Rails`) will not be available inside the hooks.
55
+
56
+ ```ruby
57
+ # config/puma.rb
58
+ before_fork do
59
+ # Add code to run inside the Puma master process before it forks a worker child.
60
+ end
61
+
62
+ before_worker_boot do
63
+ # Add code to run inside the Puma worker process after forking.
64
+ end
65
+
66
+ after_worker_shutdown do |worker_handle|
67
+ # Add code to run inside the Puma master process after a worker exits. `worker.process_status` can be used to get the
68
+ # `Process::Status` of the exited worker.
69
+ end
70
+ ```
71
+
72
+ In addition, there are `before_refork` and `after_refork` hooks which are used only in [`fork_worker` mode](#fork-worker-cluster-mode-experimental),
73
+ when the worker 0 child process forks a grandchild worker:
74
+
75
+ ```ruby
76
+ before_refork do
77
+ # Used only when fork_worker mode is enabled. Add code to run inside the Puma worker 0
78
+ # child process before it forks a grandchild worker.
79
+ end
80
+ ```
81
+
82
+ ```ruby
83
+ after_refork do
84
+ # Used only when fork_worker mode is enabled. Add code to run inside the Puma worker 0
85
+ # child process after it forks a grandchild worker.
86
+ end
87
+ ```
88
+
89
+ Importantly, note the following considerations when Ruby forks a child process:
90
+
91
+ 1. File descriptors such as network sockets **are** copied from the parent to the forked
92
+ child process. Dual-use of the same sockets by parent and child will result in I/O conflicts
93
+ such as `SocketError`, `Errno::EPIPE`, and `EOFError`.
94
+ 2. Background Ruby threads, including threads used by various third-party gems for connection
95
+ monitoring, etc., are **not** copied to the child process. Often this does not cause
96
+ immediate problems until a third-party connection goes down, at which point there will
97
+ be no supervisor to reconnect it.
98
+
99
+ Therefore, we recommend the following:
100
+
101
+ 1. If possible, do not establish any socket connections (HTTP, database connections, etc.)
102
+ inside Puma's master process when booting.
103
+ 2. If (1) is not possible, use `before_fork` and `before_refork` to disconnect the parent's socket
104
+ connections when forking, so that they are not accidentally copied to the child process.
105
+ 3. Use `before_worker_boot` to restart any background threads on the forked child.
106
+ 4. Use `after_refork` to restart any background threads on the parent.
107
+
108
+ ## Fork-Worker Cluster Mode [Experimental]
109
+
110
+ `fork_worker` (`--fork-worker` from the CLI) is an experimental cluster-mode configuration option. This mode causes Puma to fork additional workers from worker 0, instead of directly from the master process.
111
+
112
+ ```
113
+ 10000 \_ puma 8.0.2 (tcp://0.0.0.0:9292) [puma]
114
+ 10001 \_ puma: cluster worker 0: 10000 [puma]
115
+ 10002 \_ puma: cluster worker 1: 10000 [puma]
116
+ 10003 \_ puma: cluster worker 2: 10000 [puma]
117
+ 10004 \_ puma: cluster worker 3: 10000 [puma]
118
+ ```
119
+
120
+ The `fork_worker` option allows your application to be initialized only once for copy-on-write memory savings, and it has two additional advantages:
121
+
122
+ 1. **Compatible with phased restart.** With `preload_app!` disabled, the master process doesn't load the application, so this mode works with phased restart (`SIGUSR1` or `pumactl phased-restart`). When worker 0 reloads as part of a phased restart, it initializes a new copy of your application first, then the other workers reload by forking from this new worker already containing the new preloaded application.
123
+
124
+ This allows a phased restart to complete as quickly as a hot restart (`SIGUSR2` or `pumactl restart`), while still minimizing downtime by staggering the restart across cluster workers.
125
+
126
+ 2. **'Refork' for additional copy-on-write improvements in running applications.** Fork-worker mode introduces a new `refork` command that re-loads all nonzero workers by re-forking them from worker 0.
127
+
128
+ This command can potentially improve memory utilization in large or complex applications that don't fully pre-initialize on startup, because the re-forked workers can share copy-on-write memory with a worker that has been running for a while and serving requests.
129
+
130
+ You can trigger a refork by sending the cluster the `SIGURG` signal or running the `pumactl refork` command at any time. A refork will also automatically trigger once, after a certain number of requests have been processed by worker 0 (default 1000). To configure the number of requests before the auto-refork, pass a positive integer argument to `fork_worker` (e.g., `fork_worker 1000`), or `0` to disable.
131
+
132
+ ### Usage Considerations
133
+
134
+ - `fork_worker` introduces new `before_refork` and `after_refork` configuration hooks. Note the following:
135
+ - When initially forking the parent process to the worker 0 child, `before_fork` will trigger on the parent process and `before_worker_boot` will trigger on the worker 0 child as normal.
136
+ - When forking the worker 0 child to grandchild workers, `before_refork` and `after_refork` will trigger on the worker 0 child, and `before_worker_boot` will trigger on each grandchild worker.
137
+ - For clarity, `before_fork` does not trigger on worker 0, and `after_refork` does not trigger on the grandchild.
138
+ - As a general migration guide:
139
+ - Copy any logic within your existing `before_fork` hook to the `before_refork` hook.
140
+ - Consider copying logic from your `before_worker_boot` hook to the `after_refork` hook, if it is needed to reset the state of worker 0 after it forks.
141
+
142
+ ### Limitations
143
+
144
+ - This mode is still very experimental so there may be bugs or edge-cases, particularly around expected behavior of existing hooks. Please open a [bug report](https://github.com/puma/puma/issues/new?template=bug_report.md) if you encounter any issues.
145
+
146
+ - In order to fork new workers cleanly, worker 0 shuts down its server and stops serving requests so there are no open file descriptors or other kinds of shared global state between processes, and to maximize copy-on-write efficiency across the newly-forked workers. This may temporarily reduce total capacity of the cluster during a phased restart / refork.
147
+
148
+ - In a cluster with `n` workers, a normal phased restart stops and restarts workers one by one while the application is loaded in each process, so `n-1` workers are available serving requests during the restart. In a phased restart in fork-worker mode, the application is first loaded in worker 0 while `n-1` workers are available, then worker 0 remains stopped while the rest of the workers are reloaded one by one, leaving only `n-2` workers to be available for a brief period of time. Reloading the rest of the workers should be quick because the application is preloaded at that point, but there may be situations where it can take longer (slow clients, long-running application code, slow worker-fork hooks, etc).
149
+
150
+ ## Mold-Worker Cluster Mode [Experimental]
151
+
152
+ `mold_worker` (`--mold-worker` from the CLI) is an alternative to `fork_worker`. Instead of forking from a worker that also serves requests, Puma promotes a worker to a "mold", which stops serving requests and only forks new workers. Because the mold never serves traffic, a slow request, timeout or memory limit can't take it down mid-refork.
153
+
154
+ ```
155
+ 10000 \_ puma 8.0.2 (tcp://0.0.0.0:9292) [puma]
156
+ 10005 \_ puma: mold 2: 10000 [puma]
157
+ 10011 \_ puma: cluster worker 0: 10000 [puma]
158
+ 10012 \_ puma: cluster worker 1: 10000 [puma]
159
+ 10013 \_ puma: cluster worker 2: 10000 [puma]
160
+ ```
161
+
162
+ Workers are forked from the master at boot. Each request threshold (default `1000`) promotes the busiest worker to a new mold, retires the previous one, and reforks every worker from the new mold.
163
+
164
+ ```ruby
165
+ mold_worker 1000, 2000, 4000
166
+ ```
167
+
168
+ ### Usage Considerations
169
+
170
+ - Thresholds are per worker, counted from when that worker booted. Workers forked from a mold start again at zero, so with the config above a worker is promoted after 1000 requests, and a worker from that generation is promoted after another 2000.
171
+ - After the last threshold, molds are only replaced by `SIGURG` or `pumactl refork`, which promote the busiest worker at any time.
172
+ - A phased restart (`SIGUSR1` or `pumactl phased-restart`) retires the mold and forks workers from the master, so new code is loaded, then starts the thresholds again. As with any phased restart, this requires `preload_app!` to be disabled.
173
+ - `mold_worker` cannot be combined with `fork_worker`.
174
+ - On Linux 3.4+, workers are reparented to the master rather than orphaned if their mold exits.
175
+ - `mold_worker` introduces new `after_mold_promotion` and `before_mold_shutdown` configuration hooks.
176
+ - `after_mold_promotion` runs in the mold after it stops serving requests, before it forks any workers. Use it for what you would do in `before_refork`, such as closing connections or running garbage collection.
177
+ - `before_mold_shutdown` runs in the mold before it exits.
178
+ - `before_worker_boot` runs in each forked worker, as usual. Use it for what you would do in `after_refork`.
179
+
180
+ ## Using gRPC with Puma in Clustered Mode
181
+
182
+ This guide shows how to set up gRPC with Puma in a clustered environment using Puma's hooks to manage gRPC's lifecycle methods during forking.
183
+
184
+ ### The Problem
185
+
186
+ In a clustered Puma setup, you might encounter the following error when using gRPC:
187
+
188
+ ```
189
+ grpc cannot be used between calls to GRPC.prefork and GRPC.postfork_child or GRPC.postfork_parent
190
+ ```
191
+
192
+ To work correctly, gRPC needs these methods called at specific points in the process lifecycle:
193
+ - `GRPC.prefork`: Called before forking.
194
+ - `GRPC.postfork_child`: Called in the child process after forking.
195
+ - `GRPC.postfork_parent`: Called in the parent process after forking.
196
+
197
+ Puma provides hooks such as `before_worker_fork`, `after_worker_fork`, and `before_worker_boot` to execute code during these lifecycle events. Understanding the behavior of these hooks is key to ensuring gRPC operates correctly in a clustered setup.
198
+
199
+ ### The Solution
200
+
201
+ #### Example Configuration
202
+
203
+ This configuration integrates gRPC's lifecycle methods in a clustered Puma setup and works whether preloading is enabled or not.
204
+
205
+ ```ruby
206
+ # config/puma.rb
207
+
208
+ is_mac = RUBY_PLATFORM.include?("darwin")
209
+
210
+ before_worker_fork do |index|
211
+ GRPC.prefork unless is_mac
212
+ end
213
+
214
+ after_worker_fork do |index|
215
+ GRPC.postfork_parent unless is_mac
216
+ end
217
+
218
+ before_worker_boot do
219
+ GRPC.postfork_child unless is_mac
220
+ end
221
+ ```
222
+
223
+ #### Understanding the Lifecycle and Hooks
224
+
225
+ Puma's hooks determine when to call gRPC's lifecycle methods. Each hook plays a specific role in managing the lifecycle during forking:
226
+
227
+ - **`before_worker_fork`**:
228
+ - This hook runs before forking workers and is where you call `GRPC.prefork`.
229
+ - In preloading setups (default in Puma v7), it runs in the **master process** before workers are forked, as the application is preloaded in the master process.
230
+ - Without preloading, it still runs in the **master process** before forking workers, but the application is not preloaded.
231
+ - `GRPC.prefork` is called here to prepare GRPC for the forking process.
232
+
233
+ - **`after_worker_fork`**:
234
+ - This hook always runs in the **master process** after a worker is forked, regardless of whether preloading is enabled.
235
+ - Call `GRPC.postfork_parent` here to finalize the master process's state after forking.
236
+
237
+ - **`before_worker_boot`**:
238
+ - This hook always runs in the **worker process** after it is forked, regardless of whether preloading is enabled.
239
+ - Call `GRPC.postfork_child` here to finalize the worker's state.
240
+
241
+ **Note**: On macOS, these methods are skipped because gRPC does not require them due to differences in how forking works.
@@ -0,0 +1,78 @@
1
+ # Configuration
2
+
3
+ ## Configuration File
4
+
5
+ You can also provide a configuration file with the `-C` (or `--config`) flag:
6
+
7
+ ```
8
+ $ puma -C /path/to/config
9
+ ```
10
+
11
+ If no configuration file is specified, Puma will look for a configuration file at `config/puma.rb`. If an environment is specified (via the `--environment` flag or through the `APP_ENV`, `RACK_ENV`, or `RAILS_ENV` environment variables) Puma looks for a configuration file at `config/puma/<environment_name>.rb` and then falls back to `config/puma.rb`.
12
+
13
+ If you want to prevent Puma from looking for a configuration file in those locations, include the `--no-config` flag:
14
+
15
+ ```
16
+ $ puma --no-config
17
+
18
+ # or
19
+
20
+ $ puma -C "-"
21
+ ```
22
+
23
+ The other side-effects of setting the environment are whether to show stack traces (in `development` or `test`), and setting RACK_ENV may potentially affect middleware looking for this value to change their behavior. The default puma RACK_ENV value is `development`. You can see all config default values in `Puma::Configuration#puma_default_options` or [configuration.rb](https://github.com/puma/puma/blob/61c6213fbab/lib/puma/configuration.rb#L182-L204).
24
+
25
+ ## Thread Pool
26
+
27
+ Puma uses a thread pool. You can set the minimum and maximum number of threads that are available in the pool with the `-t` (or `--threads`) flag:
28
+
29
+ ```
30
+ $ puma -t 8:32
31
+ ```
32
+
33
+ Puma will automatically scale the number of threads, from the minimum until it caps out at the maximum, based on how much traffic is present. The current default is `0:16` and on MRI is `0:5`. Feel free to experiment, but be careful not to set the number of maximum threads to a large number, as you may exhaust resources on the system (or cause contention for the Global VM Lock, when using MRI).
34
+
35
+ Be aware that additionally Puma creates threads on its own for internal purposes (e.g. handling slow clients). So, even if you specify -t 1:1, expect around 7 threads created in your application.
36
+
37
+ ## Master process lifecycle hooks
38
+
39
+ Puma's configuration DSL provides master process lifecycle hooks `after_booted`, `before_restart`, and `after_stopped`
40
+ which may be used to specify code blocks to run on each event:
41
+
42
+ ```ruby
43
+ # config/puma.rb
44
+ after_booted do
45
+ # Add code to run in the Puma master process after it boots,
46
+ # and also after a phased restart completes.
47
+ end
48
+
49
+ before_restart do
50
+ # Add code to run in the Puma master process when it receives
51
+ # a restart command but before it restarts.
52
+ end
53
+
54
+ after_stopped do
55
+ # Add code to run in the Puma master process after outstanding
56
+ # requests have finished and Puma has stopped.
57
+ end
58
+ ```
59
+
60
+ ## Error handling
61
+
62
+ If Puma encounters an error outside of the context of your application, it will respond with a 400/500 and a simple
63
+ textual error message (see `Puma::Server#lowlevel_error` or [server.rb](https://github.com/puma/puma/blob/main/lib/puma/server.rb)).
64
+ You can specify custom behavior for this scenario. For example, you can report the error to your third-party
65
+ error-tracking service (in this example, [rollbar](https://rollbar.com)):
66
+
67
+ ```ruby
68
+ lowlevel_error_handler do |e, env, status|
69
+ if status == 400
70
+ message = "The server could not process the request due to an error, such as an incorrectly typed URL, malformed syntax, or a URL that contains illegal characters.\n"
71
+ else
72
+ message = "An error has occurred, and engineers have been informed. Please reload the page. If you continue to have problems, contact support@example.com\n"
73
+ Rollbar.critical(e)
74
+ end
75
+
76
+ [status, {}, [message]]
77
+ end
78
+ ```
@@ -1,3 +1,21 @@
1
+ # Control/Status Server
2
+
3
+ Puma has a built-in status and control app that can be used to query and control Puma.
4
+
5
+ ```
6
+ $ puma --control-url tcp://127.0.0.1:9293 --control-token foo
7
+ ```
8
+
9
+ Puma will start the control server on localhost port 9293. All requests to the control server will need to include a control token (in this case, `token=foo`) as a query parameter. This allows for simple authentication. Check out `Puma::App::Status` or [status.rb](https://github.com/puma/puma/blob/main/lib/puma/app/status.rb) to see what the status app has available.
10
+
11
+ You can also interact with the control server via `pumactl`. This command will restart Puma:
12
+
13
+ ```
14
+ $ pumactl --control-url 'tcp://127.0.0.1:9293' --control-token foo restart
15
+ ```
16
+
17
+ To see a list of `pumactl` options, use `pumactl --help`.
18
+
1
19
  ## Accessing stats
2
20
 
3
21
  Stats can be accessed in two ways:
@@ -6,8 +24,6 @@ Stats can be accessed in two ways:
6
24
 
7
25
  `$ pumactl stats` or `GET /stats`
8
26
 
9
- [Read more about `pumactl` and the control server in the README.](https://github.com/puma/puma#controlstatus-server).
10
-
11
27
  ### Puma.stats
12
28
 
13
29
  `Puma.stats` produces a JSON string. `Puma.stats_hash` produces a ruby hash.
@@ -70,7 +86,7 @@ When Puma runs in single mode, these stats are available at the top level. When
70
86
 
71
87
  ### cluster mode
72
88
 
73
- * phase: which phase of restart the process is in, during [phased restart](https://github.com/puma/puma/blob/main/docs/restart.md)
89
+ * phase: which phase of restart the process is in, during [phased restart](restart.md)
74
90
  * workers: ??
75
91
  * booted_workers: how many workers are currently running?
76
92
  * old_workers: ??
@@ -146,3 +162,7 @@ Here are two example stats hashes produced by `Puma.stats`:
146
162
  ]
147
163
  }
148
164
  ```
165
+
166
+ ## Monitoring
167
+
168
+ * [puma-status](https://github.com/ylecuyer/puma-status) — Monitor CPU/Mem/Load of running puma instances from the CLI
@@ -41,7 +41,7 @@ Set your config with the following process:
41
41
 
42
42
  For most deployments, adding `concurrent-ruby` and using `workers :auto` is the right starting point.
43
43
 
44
- See [`workers :auto` gotchas](../lib/puma/dsl.rb).
44
+ See [`workers :auto` gotchas](../../lib/puma/dsl.rb).
45
45
 
46
46
  ## Worker utilization
47
47
 
@@ -117,11 +117,13 @@ and to get paged at 3 AM. Do yourself a favor, at least use the process monitori
117
117
  your OS comes with, be it `sysvinit` or `systemd`. Or branch out and use `runit`
118
118
  or hell, even `monit`.
119
119
 
120
+ Additionally, Puma has support for built-in daemonization via the [puma-daemon](https://github.com/kigster/puma-daemon) ruby gem. The gem restores the `daemonize` option that was removed from Puma starting version 5, but only for MRI Ruby.
121
+
120
122
  ## Restarting
121
123
 
122
124
  You probably will want to deploy some new code at some point, and you'd like
123
125
  Puma to start running that new code. There are a few options for restarting
124
- Puma, described separately in our [restart documentation](restart.md).
126
+ Puma, described separately in our [restart documentation](../restart.md).
125
127
 
126
128
  ## Migrating from Unicorn
127
129
 
@@ -132,6 +134,20 @@ Puma, described separately in our [restart documentation](restart.md).
132
134
  * As you grow more confident in the thread-safety of your app, you can tune the
133
135
  workers down and the threads up.
134
136
 
135
- ## Ubuntu / Systemd (Systemctl) Installation
137
+ ## Process monitors and guides
138
+
139
+ It is common to use process monitors with Puma. Modern process monitors like systemd or rc.d
140
+ provide continuous monitoring and restarts for increased reliability in production environments:
141
+
142
+ * [rc.d](rc.d/README.md)
143
+ * [systemd](systemd.md)
144
+ * [Kubernetes](kubernetes.md)
145
+ * [nginx](nginx.md)
146
+
147
+ Community guides:
148
+
149
+ * [Deploying Puma on OpenBSD using relayd and httpd](https://gist.github.com/anon987654321/4532cf8d6c59c1f43ec8973faa031103)
150
+
151
+ ## Capistrano
136
152
 
137
- See [systemd.md](systemd.md)
153
+ Puma has support for Capistrano with an [external gem](https://github.com/seuros/capistrano-puma).
@@ -69,5 +69,5 @@ More discussions and links to relevant articles can be found in https://github.c
69
69
 
70
70
  ## Workers Per Pod, and Other Config Issues
71
71
 
72
- See our [deployment docs](./deployment.md) for more information about how to correctly size your pods and choose the right number of workers and threads.
72
+ See our [deployment docs](README.md) for more information about how to correctly size your pods and choose the right number of workers and threads.
73
73
 
data/docs/plugins.md CHANGED
@@ -1,4 +1,4 @@
1
- ## Plugins
1
+ # Plugins
2
2
 
3
3
  Puma 3.0 added support for plugins that can augment configuration and service
4
4
  operations.
@@ -39,4 +39,63 @@ public API for plugins.
39
39
 
40
40
  ## Binder hooks
41
41
 
42
- There's a `Puma::Binder#before_parse` method that allows adding a proc to run before the body of `Puma::Binder#parse`. Example of usage can be found in [that repository](https://github.com/anchordotdev/puma-acme/blob/v0.1.3/lib/puma/acme/plugin.rb#L97-L118) (`before_parse_hook` could be renamed `before_parse`, making monkey patching of [binder.rb](https://github.com/anchordotdev/puma-acme/blob/v0.1.3/lib/puma/acme/binder.rb) unnecessary).
42
+ There's a `Puma::Binder#before_parse` method that allows adding a proc to run before the body of `Puma::Binder#parse`. Example of usage can be found in [that repository](https://github.com/anchordotdev/puma-acme/blob/v0.1.3/lib/puma/acme/plugin.rb#L97-L118) (`before_parse_hook` could be renamed `before_parse`, making monkey patching of [binder.rb](https://github.com/anchordotdev/puma-acme/blob/v0.1.3/lib/puma/acme/binder.rb) unnecessary).
43
+
44
+ ## Community plugins
45
+
46
+ * [puma-metrics](https://github.com/harmjanblok/puma-metrics) — export Puma metrics to Prometheus
47
+ * [puma-plugin-statsd](https://github.com/yob/puma-plugin-statsd) — send Puma metrics to statsd
48
+ * [puma-plugin-systemd](https://github.com/sj26/puma-plugin-systemd) — deeper integration with systemd for notify, status and watchdog. Puma 5.1.0 integrated notify and watchdog, which probably conflicts with this plugin. Puma 6.1.0 added status support which obsoletes the plugin entirely.
49
+ * [puma-plugin-telemetry](https://github.com/babbel/puma-plugin-telemetry) - telemetry plugin for Puma offering various targets to publish
50
+ * [puma-acme](https://github.com/anchordotdev/puma-acme) - automatic SSL/HTTPS certificate provisioning and setup
51
+
52
+ ## Example: stopping Puma via Redis
53
+
54
+ ```ruby
55
+ require 'puma/plugin'
56
+ require 'redis'
57
+
58
+ # How to stop Puma on Heroku
59
+ # - You can't use normal methods because the dyno is not accessible
60
+ # - There's no file system, no way to send signals
61
+ # but ...
62
+ # - You can use Redis or Memcache; any network distributed key-value
63
+ # store
64
+
65
+ # 1. Add this plugin to your 'lib' directory
66
+ # 2. In the `puma.rb` config file add the following lines
67
+ # === Plugins ===
68
+ # require './lib/puma/plugin/redis_stop_puma'
69
+ # plugin 'redis_stop_puma'
70
+ # 3. Now, when you set the redis key "puma::restart::web.1", your web.1 dyno
71
+ # will restart
72
+ # 4. Sniffing the Heroku logs for R14 errors is application (and configuration)
73
+ # specific. I use the Logentries service, watch for the pattern and the call
74
+ # a webhook back into my app to set the Redis key. YMMV
75
+
76
+ # You can test this locally by setting the DYNO environment variable when
77
+ # when starting puma, e.g. `DYNO=pants.1 puma`
78
+
79
+ Puma::Plugin.create do
80
+ def start(launcher)
81
+
82
+ hostname = ENV['DYNO']
83
+ return unless hostname
84
+
85
+ redis = Redis.new(url: ENV.fetch('REDIS_URL', nil))
86
+ return unless redis.ping == 'PONG'
87
+
88
+ in_background do
89
+ while true
90
+ sleep 2
91
+ if message = redis.get("puma::restart::#{hostname}")
92
+ redis.del("puma::restart::#{hostname}")
93
+ $stderr.puts message
94
+ launcher.stop
95
+ break
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
101
+ ```
data/docs/puma_support.md CHANGED
@@ -8,12 +8,26 @@ This document's purpose is to help users and contributors of this library make f
8
8
 
9
9
  Puma is a community-run project. "Support" means "what do the maintainers pay attention to and what are they likely to merge", and doesn't mean that we do anything by any particular date, or even at all. We may all jet off to a private island tomorrow and never speak again.
10
10
 
11
- But, if we do decide to keep devoting our free time to open source software, we will **support the environments (combinations of Ruby version, Ruby implementation, Rack version, and operating system) which run on our CI.**
11
+ But, if we do decide to keep devoting our free time to open source software, we will **support the Ruby versions, Ruby implementations, Rack versions, and operating systems which run on our CI**, in any combination, even combinations that CI doesn't run directly.
12
12
 
13
13
  If you open a PR or bug report for a combination of those factors outside of our CI matrix, we may still accept it if it's a small and low-risk fix.
14
14
 
15
15
  We may add environments to CI at any time, but we only drop a supported environment in a minor or major release.
16
16
 
17
+ ## CI matrix
18
+
19
+ CI aims for the most coverage with the fewest jobs.
20
+
21
+ Every OS and architecture runs the oldest supported Ruby on its oldest runner image, and the newest Ruby on its newest image.
22
+
23
+ On x64, a few more jobs fill in the gaps:
24
+
25
+ - The newest Ubuntu image that can build every supported Ruby runs all of them.
26
+ - The newest Ubuntu image also runs Ruby head with YJIT, plus JRuby and TruffleRuby and their head versions.
27
+ - The newest Windows image also runs the ucrt and mswin builds.
28
+ - The oldest Ubuntu and Windows images also run the oldest Ruby without SSL.
29
+ - The oldest Ubuntu image also runs the oldest Ruby with the oldest supported Rack.
30
+
17
31
  ## Puma release support policy
18
32
 
19
33
  By default, Puma supports one release version, the latest release. That means if there is a bug in 3.2.1 (made-up numbers for example only), but the latest release is 4.3.2, the bug must be reproduced in 4.3.2 to qualify for support.
data/docs/restart.md CHANGED
@@ -1,4 +1,8 @@
1
- Puma provides three distinct kinds of restart operations, each for different use cases. This document describes "hot restarts" and "phased restarts." The third kind of restart operation is called "refork" and is described in the documentation for [`fork_worker` and `mold_worker`](fork_worker.md).
1
+ # Restart
2
+
3
+ Puma includes the ability to restart itself. When available (MRI, Rubinius, JRuby), Puma performs a "hot restart". This is the same functionality available in *Unicorn* and *NGINX* which keep the server sockets open between restarts. This makes sure that no pending requests are dropped while the restart is taking place.
4
+
5
+ Puma provides three distinct kinds of restart operations, each for different use cases. This document describes "hot restarts" and "phased restarts." The third kind of restart operation is called "refork" and is described in the documentation for [`fork_worker` and `mold_worker`](cluster_mode.md#fork-worker-cluster-mode-experimental).
2
6
 
3
7
  ## Hot restart
4
8
 
data/docs/signals.md CHANGED
@@ -1,3 +1,5 @@
1
+ # Signals
2
+
1
3
  The [unix signal](https://en.wikipedia.org/wiki/Unix_signal) is a method of sending messages between [processes](https://en.wikipedia.org/wiki/Process_(computing)). When a signal is sent, the operating system interrupts the target process's normal flow of execution. There are standard signals that are used to stop a process, but there are also custom signals that can be used for other purposes. This document is an attempt to list all supported signals that Puma will respond to. In general, signals need only be sent to the master process of a cluster.
2
4
 
3
5
  ## Sending Signals
@@ -10,7 +10,7 @@ Puma 5 brings new experimental performance features, a few quality-of-life featu
10
10
  2. Upgrade to version 5.0 in your Gemfile and deploy.
11
11
  3. Try the new performance experiments outlined below and report your results back to the Puma issue tracker.
12
12
 
13
- Puma 5 was named Spoony Bard by our newest supercontributor, [@wjordan](https://github.com/puma/puma/commits?author=wjordan). Will brought you one of our new perf features for this release, as well as [many other fixes and refactors.](https://github.com/puma/puma/commits?author=wjordan) If you'd like to name a Puma release in the future, take a look at [CONTRIBUTING.md](../CONTRIBUTING.md) and get started helping us out :)
13
+ Puma 5 was named Spoony Bard by our newest supercontributor, [@wjordan](https://github.com/puma/puma/commits?author=wjordan). Will brought you one of our new perf features for this release, as well as [many other fixes and refactors.](https://github.com/puma/puma/commits?author=wjordan) If you'd like to name a Puma release in the future, take a look at [CONTRIBUTING.md](../../CONTRIBUTING.md) and get started helping us out :)
14
14
 
15
15
  Puma 5 also welcomes [@MSP-Greg](https://github.com/puma/puma/commits?author=MSP-Greg) as our newest committer. Greg has been instrumental in improving our CI setup and SSL features. Greg also [named our 4.3.0 release](https://github.com/puma/puma/releases/tag/v4.3.0): Mysterious Traveller.
16
16
 
@@ -70,7 +70,7 @@ Puma 5 introduces an experimental new cluster-mode configuration option, `fork_w
70
70
 
71
71
  It is compatible with phased restarts. It also may improve memory usage because the worker process loads additional code after processing requests.
72
72
 
73
- To learn more about using `refork` and `fork_worker`, see ['Fork Worker'](fork_worker.md).
73
+ To learn more about using `refork` and `fork_worker`, see ['Fork Worker'](../cluster_mode.md#fork-worker-cluster-mode-experimental).
74
74
 
75
75
  ### What else is new?
76
76
 
@@ -89,7 +89,7 @@ To learn more about using `refork` and `fork_worker`, see ['Fork Worker'](fork_w
89
89
  * If you have been using the `--control` CLI option, update your scripts to use `--control-url`.
90
90
  * If you are using `worker_directory` in your config file, change it to `directory`.
91
91
  * If you are running MRI, default thread count on Puma is now 5, not 16. This may change the amount of threads running in your threadpool. We believe 5 is a better default for most Ruby web applications on MRI. Higher settings increase latency by causing GVL contention.
92
- * If you are using a worker count of more than 1, set using `WEB_CONCURRENCY`, Puma will now preload the application by default (disable with `preload_app! false`). We believe this is a better default, but may cause issues in non-Rails applications if you do not have the proper `before` and `after` fork hooks configured. See documentation for your framework. Rails users do not need to change anything. **Please note that it is not possible to use [the phased restart](restart.md) with preloading.**
92
+ * If you are using a worker count of more than 1, set using `WEB_CONCURRENCY`, Puma will now preload the application by default (disable with `preload_app! false`). We believe this is a better default, but may cause issues in non-Rails applications if you do not have the proper `before` and `after` fork hooks configured. See documentation for your framework. Rails users do not need to change anything. **Please note that it is not possible to use [the phased restart](../restart.md) with preloading.**
93
93
  * tcp mode and daemonization have been removed without replacement. For daemonization, please use a modern process management solution, such as systemd or monit.
94
94
  * `connected_port` was renamed to `connected_ports` and now returns an Array, not an Integer.
95
95
 
@@ -9,9 +9,9 @@ Here's what you should do:
9
9
  1. Review the Upgrade section below to look for breaking changes that could affect you.
10
10
  2. Upgrade to version 6.0 in your Gemfile and deploy.
11
11
  3. Open up a new bug issue if you find any problems.
12
- 4. Join us in building Puma! We welcome first-timers. See [CONTRIBUTING.md](../CONTRIBUTING.md).
12
+ 4. Join us in building Puma! We welcome first-timers. See [CONTRIBUTING.md](../../CONTRIBUTING.md).
13
13
 
14
- For a complete list of changes, see [History.md](../History.md).
14
+ For a complete list of changes, see [History.md](../../History.md).
15
15
 
16
16
  ## What's New
17
17
 
@@ -7,9 +7,9 @@ Here's what you should do:
7
7
  1. Review the Upgrade section below to look for breaking changes that could affect you.
8
8
  2. Upgrade to version 7.0 in your Gemfile and deploy.
9
9
  3. Open up a new bug issue if you find any problems.
10
- 4. Join us in building Puma! We welcome first-timers. See [CONTRIBUTING.md](../CONTRIBUTING.md).
10
+ 4. Join us in building Puma! We welcome first-timers. See [CONTRIBUTING.md](../../CONTRIBUTING.md).
11
11
 
12
- For a complete list of changes, see [History.md](../History.md).
12
+ For a complete list of changes, see [History.md](../../History.md).
13
13
 
14
14
  ## What's New
15
15
 
@@ -7,9 +7,9 @@ Here's what you should do:
7
7
  1. Review the Upgrade section below to look for breaking changes that could affect you.
8
8
  2. Upgrade to version 8.0 in your Gemfile and deploy.
9
9
  3. Open up a new bug issue if you find any problems.
10
- 4. Join us in building Puma! We welcome first-timers. See [CONTRIBUTING.md](./CONTRIBUTING.md).
10
+ 4. Join us in building Puma! We welcome first-timers. See [CONTRIBUTING.md](../../CONTRIBUTING.md).
11
11
 
12
- For a complete list of changes, see [History.md](./History.md).
12
+ For a complete list of changes, see [History.md](../../History.md).
13
13
 
14
14
  ## What's New
15
15
 
data/lib/puma/cluster.rb CHANGED
@@ -269,7 +269,6 @@ module Puma
269
269
  @status = :stop if @status == :run
270
270
  wakeup!
271
271
  @control&.stop true
272
- Process.waitall
273
272
  end
274
273
 
275
274
  def halt
data/lib/puma/const.rb CHANGED
@@ -100,7 +100,7 @@ module Puma
100
100
  # too taxing on performance.
101
101
  module Const
102
102
 
103
- PUMA_VERSION = VERSION = "8.1.0"
103
+ PUMA_VERSION = VERSION = "8.1.1"
104
104
  CODE_NAME = "Puma Psychosis"
105
105
 
106
106
  PUMA_SERVER_STRING = ["puma", PUMA_VERSION, CODE_NAME].join(" ").freeze
data/lib/puma/minissl.rb CHANGED
@@ -205,10 +205,7 @@ module Puma
205
205
  private :queue_ciphertext
206
206
 
207
207
  def flush_write_buffer
208
- return if @write_buffer.empty?
209
-
210
- @socket.write @write_buffer
211
- @write_buffer = +''
208
+ @socket.wait_writable until flush_write_buffer_nonblock
212
209
  end
213
210
  private :flush_write_buffer
214
211
 
Binary file