pitchfork 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/Gemfile.lock +2 -2
- data/docs/Application_Timeouts.md +1 -1
- data/docs/CONFIGURATION.md +77 -11
- data/ext/pitchfork_http/pitchfork_http.c +166 -166
- data/lib/pitchfork/chunked.rb +1 -1
- data/lib/pitchfork/configurator.rb +17 -6
- data/lib/pitchfork/http_server.rb +104 -25
- data/lib/pitchfork/soft_timeout.rb +113 -0
- data/lib/pitchfork/version.rb +1 -1
- data/lib/pitchfork/worker.rb +12 -8
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ccd444fbdc89d5a253819e7be03e5d097c5aaf8b061980e15d4ec5326d2c54b5
|
4
|
+
data.tar.gz: f300bd3135e8d8d9e15f14dfe2780c75521ececeb72b8245fef0380e2ba338f5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b054a33d46f4b60c14e44fbac330bc4318a1b52259e89f2e8a1c16a58d8467f02eef981dbe018906a0c7a027c98db75a8efd483619d7ea5e2ece234b30b3846f
|
7
|
+
data.tar.gz: b12a622275fe638d49be5d9457d11309421119f9628044dec9898231f83425cab6aa6434b9f42372c5f8954b261f7e979e300a41fa75c39172fb8e1832cb0805
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
# Unreleased
|
2
2
|
|
3
|
+
- Added a soft timeout in addition to the historical Unicorn hard timeout.
|
4
|
+
On soft timeout, the `after_worker_timeout` callback is invoked.
|
5
|
+
- Implement `after_request_complete` callback.
|
6
|
+
|
7
|
+
# 0.4.1
|
8
|
+
|
9
|
+
- Avoid a Rack 3 deprecation warning.
|
10
|
+
- Fix handling on non-ASCII cookies.
|
11
|
+
- Log unknown process being reaped at INFO level.
|
12
|
+
|
3
13
|
# 0.4.0
|
4
14
|
|
5
15
|
- Preserve the current thread when reforking.
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
pitchfork (0.
|
4
|
+
pitchfork (0.5.0)
|
5
5
|
rack (>= 2.0)
|
6
6
|
raindrops (~> 0.7)
|
7
7
|
|
@@ -12,7 +12,7 @@ GEM
|
|
12
12
|
nio4r (2.5.8)
|
13
13
|
puma (6.1.1)
|
14
14
|
nio4r (~> 2.0)
|
15
|
-
rack (3.0.
|
15
|
+
rack (3.0.8)
|
16
16
|
raindrops (0.20.1)
|
17
17
|
rake (13.0.6)
|
18
18
|
rake-compiler (1.2.1)
|
@@ -70,5 +70,5 @@ handle network/server failures.
|
|
70
70
|
The `timeout` mechanism in pitchfork is an extreme solution that should
|
71
71
|
be avoided whenever possible.
|
72
72
|
It will help preserve the platform if your application or a dependency
|
73
|
-
has a bug that cause it to either get stuck or
|
73
|
+
has a bug that cause it to either get stuck or be too slow, but it is not a
|
74
74
|
solution to such bugs, merely a mitigation.
|
data/docs/CONFIGURATION.md
CHANGED
@@ -173,33 +173,55 @@ The following options may be specified (but are generally not needed):
|
|
173
173
|
### `timeout`
|
174
174
|
|
175
175
|
```ruby
|
176
|
-
timeout 10
|
176
|
+
timeout 10, cleanup: 3
|
177
177
|
```
|
178
178
|
|
179
|
-
Sets the timeout
|
180
|
-
Workers handling the request/app.call/response cycle taking longer than
|
181
|
-
this time period will be forcibly killed (via `SIGKILL`).
|
179
|
+
Sets the timeout for worker processes to a number of seconds.
|
182
180
|
|
183
|
-
|
181
|
+
Note that Pitchfork has two layers of timeout.
|
182
|
+
|
183
|
+
A first "soft" timeout will invoke the `after_worker_timeout` from
|
184
|
+
within the worker (but from a background thread) and then call `exit`
|
185
|
+
to terminate the worker cleanly.
|
186
|
+
|
187
|
+
The second "hard" timeout, is the sum of `timeout` and `cleanup`.
|
188
|
+
Workers taking longer than this time period to be ready to handle a new
|
189
|
+
request will be forcibly killed (via `SIGKILL`).
|
190
|
+
|
191
|
+
Neither of these timeout mecanisms should be routinely relied on, and should
|
184
192
|
instead be considered as a last line of defense in case you application
|
185
193
|
is impacted by bugs causing unexpectedly slow response time, or fully stuck
|
186
194
|
processes.
|
187
195
|
|
196
|
+
If some of the application endpoints require an unreasonably large timeout,
|
197
|
+
rather than to increase the global application timeout, it is possible to
|
198
|
+
adjust it on a per request basis via the rack request environment:
|
199
|
+
|
200
|
+
```ruby
|
201
|
+
class MyMiddleware
|
202
|
+
def call(env)
|
203
|
+
if slow_endpoint?(env)
|
204
|
+
# Give 10 more seconds
|
205
|
+
env["pitchfork.timeout"]&.extend_deadline(10)
|
206
|
+
end
|
207
|
+
@app.call(env)
|
208
|
+
end
|
209
|
+
end
|
210
|
+
```
|
211
|
+
|
188
212
|
Make sure to read the guide on [application timeouts](Application_Timeouts.md).
|
189
213
|
|
190
|
-
This configuration defaults to a (too) generous 20 seconds
|
191
|
-
|
192
|
-
profile.
|
214
|
+
This configuration defaults to a (too) generous 20 seconds for the soft timeout
|
215
|
+
and an extra 2 seconds for the hard timeout. It is highly recommended to set a
|
216
|
+
stricter one based on your application profile.
|
193
217
|
|
194
|
-
This timeout is enforced by the master process itself and not subject
|
195
|
-
to the scheduling limitations by the worker process.
|
196
218
|
Due the low-complexity, low-overhead implementation, timeouts of less
|
197
219
|
than 3.0 seconds can be considered inaccurate and unsafe.
|
198
220
|
|
199
221
|
For running Pitchfork behind nginx, it is recommended to set
|
200
222
|
"fail_timeout=0" for in your nginx configuration like this
|
201
223
|
to have nginx always retry backends that may have had workers
|
202
|
-
SIGKILL-ed due to timeouts.
|
224
|
+
exit or be SIGKILL-ed due to timeouts.
|
203
225
|
|
204
226
|
```
|
205
227
|
upstream pitchfork_backend {
|
@@ -284,6 +306,36 @@ after_worker_ready do |server, worker|
|
|
284
306
|
end
|
285
307
|
```
|
286
308
|
|
309
|
+
### `after_worker_timeout`
|
310
|
+
|
311
|
+
Called by the worker process when the request timeout is elapsed:
|
312
|
+
|
313
|
+
```ruby
|
314
|
+
after_worker_timeout do |server, worker, timeout_info|
|
315
|
+
timeout_info.copy_thread_variables!
|
316
|
+
timeout_info.thread.kill
|
317
|
+
server.logger.error("Request timed out: #{timeout_info.rack_env.inspect}")
|
318
|
+
$stderr.puts timeout_info.thread.backtrace
|
319
|
+
end
|
320
|
+
```
|
321
|
+
|
322
|
+
Note that this callback is invoked from a different thread. You can access the
|
323
|
+
main thread via `timeout_info.thread`, as well as the rack environment via `timeout_info.rack_env`.
|
324
|
+
|
325
|
+
If you need to invoke cleanup code that rely on thread local state, you can copy
|
326
|
+
that state with `timeout_info.copy_thread_variables!`, but it's best avoided as the
|
327
|
+
thread local state could contain thread unsafe objects.
|
328
|
+
|
329
|
+
Also note that at this stage, the thread is still alive, if your callback does
|
330
|
+
substantial work, you may want to kill the thread.
|
331
|
+
|
332
|
+
After the callback is executed the worker will exit with status `0`.
|
333
|
+
|
334
|
+
It is recommended not to do slow operations in this callback, but if you
|
335
|
+
really have to, make sure to configure the `cleanup` timeout so that the
|
336
|
+
callback has time to complete before the "hard" timeout triggers.
|
337
|
+
By default the cleanup timeout is 2 seconds.
|
338
|
+
|
287
339
|
### `after_worker_exit`
|
288
340
|
|
289
341
|
Called in the master process after a worker exits.
|
@@ -297,6 +349,20 @@ after_worker_exit do |server, worker, status|
|
|
297
349
|
end
|
298
350
|
```
|
299
351
|
|
352
|
+
### `after_request_complete`
|
353
|
+
|
354
|
+
Called in the worker processes after a request has completed.
|
355
|
+
|
356
|
+
Can be used for out of band work, or to exit unhealthy workers.
|
357
|
+
|
358
|
+
```ruby
|
359
|
+
after_request_complete do |server, worker|
|
360
|
+
if something_wrong?
|
361
|
+
exit
|
362
|
+
end
|
363
|
+
end
|
364
|
+
```
|
365
|
+
|
300
366
|
## Reforking
|
301
367
|
|
302
368
|
### `refork_after`
|