Skip to content

Commit

Permalink
Add on_refork hook configuration and integration test
Browse files Browse the repository at this point in the history
  • Loading branch information
wjordan committed May 4, 2020
1 parent 0c25b37 commit 0e2fec5
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 7 deletions.
22 changes: 22 additions & 0 deletions lib/puma/dsl.rb
Expand Up @@ -492,6 +492,28 @@ def after_worker_fork(&block)

alias_method :after_worker_boot, :after_worker_fork

# When `fork_worker` is enabled, code to run in Worker 0
# before all other workers are re-forked from this process,
# after the server has temporarily stopped serving requests
# (once per complete refork cycle).
#
# This can be used to trigger extra garbage-collection to maximize
# copy-on-write efficiency, or close any connections to remote servers
# (database, Redis, ...) that were opened while the server was running.
#
# This can be called multiple times to add several hooks.
#
# @note Cluster mode with `fork_worker` enabled only.
# @example
# on_refork do
# 3.times {GC.start}
# end

def on_refork(&block)
@options[:before_refork] ||= []
@options[:before_refork] << block
end

# Code to run out-of-band when the worker is idle.
# These hooks run immediately after a request has finished
# processing and there are no busy threads on the worker.
Expand Down
12 changes: 9 additions & 3 deletions test/helpers/integration.rb
Expand Up @@ -44,12 +44,18 @@ def teardown

private

def cli_server(argv, unix: false)
def cli_server(argv, unix: false, config: nil)
if config
config_file = Tempfile.new(%w(config .rb))
config_file.write config
config_file.close
config = "-C #{config_file.path}"
end
if unix
cmd = "#{BASE} bin/puma -b unix://#{@bind_path} #{argv}"
cmd = "#{BASE} bin/puma #{config} -b unix://#{@bind_path} #{argv}"
else
@tcp_port = UniquePort.call
cmd = "#{BASE} bin/puma -b tcp://#{HOST}:#{@tcp_port} #{argv}"
cmd = "#{BASE} bin/puma #{config} -b tcp://#{HOST}:#{@tcp_port} #{argv}"
end
@server = IO.popen(cmd, "r")
wait_for_server_to_boot
Expand Down
16 changes: 12 additions & 4 deletions test/test_integration_cluster.rb
Expand Up @@ -157,13 +157,21 @@ def test_worker_timeout
RUBY
end

def test_refork
refork = Tempfile.new('refork')
cli_server "-w #{WORKERS} test/rackup/sleep.ru", config: <<RUBY
fork_worker 1
on_refork {File.write('#{refork.path}', 'Reforked')}
RUBY
pids = get_worker_pids
read_body(connect('sleep1')) until refork.read == 'Reforked'
refute_includes pids, get_worker_pids(1, WORKERS - 1)
end

private

def worker_timeout(timeout, iterations, config)
config_file = Tempfile.new(%w(worker_timeout .rb))
config_file.write config
config_file.close
cli_server "-w #{WORKERS} -t 1:1 -C #{config_file.path} test/rackup/hello.ru"
cli_server "-w #{WORKERS} -t 1:1 test/rackup/hello.ru", config: config

pids = []
Timeout.timeout(iterations * timeout + 1) do
Expand Down

0 comments on commit 0e2fec5

Please sign in to comment.