Skip to content

Commit

Permalink
Allow to use preload_app! with fork_worker (#2907)
Browse files Browse the repository at this point in the history
So far it was incompatible because true phased
restart are incompatible with preload_app.

But `fork_worker` doesn't do a phased restart
per say, it just piggy back on the implementation
to ask worker #0 to refork its siblings.

So we can just bypass that check and it works.

Co-authored-by: Jean Boussier <jean.boussier@gmail.com>
  • Loading branch information
casperisfine and byroot committed Sep 15, 2022
1 parent 317e890 commit e438b90
Show file tree
Hide file tree
Showing 2 changed files with 4 additions and 6 deletions.
4 changes: 1 addition & 3 deletions docs/fork_worker.md
Expand Up @@ -10,7 +10,7 @@ Puma 5 introduces an experimental new cluster-mode configuration option, `fork_w
10004 \_ puma: cluster worker 3: 10000 [puma]
```

Similar to the `preload_app!` option, the `fork_worker` option allows your application to be initialized only once for copy-on-write memory savings, and it has two additional advantages:
The `fork_worker` option allows your application to be initialized only once for copy-on-write memory savings, and it has two additional advantages:

1. **Compatible with phased restart.** Because the master process itself doesn't preload the application, 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.

Expand All @@ -24,8 +24,6 @@ Similar to the `preload_app!` option, the `fork_worker` option allows your appli

### Limitations

- Not compatible with the `preload_app!` option

- 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.

- 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.
Expand Down
6 changes: 3 additions & 3 deletions lib/puma/cluster.rb
Expand Up @@ -213,8 +213,8 @@ def restart
stop
end

def phased_restart
return false if @options[:preload_app]
def phased_restart(refork = false)
return false if @options[:preload_app] && !refork

@phased_restart = true
wakeup!
Expand Down Expand Up @@ -281,7 +281,7 @@ def fork_worker!
if (worker = @workers.find { |w| w.index == 0 })
worker.phase += 1
end
phased_restart
phased_restart(true)
end

# We do this in a separate method to keep the lambda scope
Expand Down

0 comments on commit e438b90

Please sign in to comment.