Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add on_booted event #2709

Merged
merged 2 commits into from
Feb 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,15 @@ before_fork do
end
```

You can also specify a block to be run after puma is booted using `on_booted`:

```ruby
# config/puma.rb
on_booted do
# configuration here
end
```

### Error handling

If puma encounters an error outside of the context of your application, it will respond with a 500 and a simple
Expand Down
2 changes: 1 addition & 1 deletion lib/puma/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ def configure_control_url(command_line_arg)
#

def setup_options
@conf = Configuration.new do |user_config, file_config|
@conf = Configuration.new({}, {events: @events}) do |user_config, file_config|
@parser = OptionParser.new do |o|
o.on "-b", "--bind URI", "URI to bind to (tcp://, unix://, ssl://)" do |arg|
user_config.bind arg
Expand Down
10 changes: 10 additions & 0 deletions lib/puma/dsl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,16 @@ def after_worker_fork(&block)

alias_method :after_worker_boot, :after_worker_fork

# Code to run after puma is booted (works for both: single and clustered)
#
# @example
# on_booted do
# puts 'After booting...'
# end
def on_booted(&block)
@config.options[:events].on_booted(&block)
end

# 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
Expand Down
8 changes: 5 additions & 3 deletions lib/rack/handler/puma.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ def config(app, options = {})
end
end

conf = ::Puma::Configuration.new(options, default_options) do |user_config, file_config, default_config|
@events = options[:events] || ::Puma::Events.new

conf = ::Puma::Configuration.new(options, default_options.merge({events: @events})) do |user_config, file_config, default_config|
if options.delete(:Verbose)
require 'rack/common_logger'
app = Rack::CommonLogger.new(app, STDOUT)
Expand Down Expand Up @@ -59,11 +61,11 @@ def config(app, options = {})
end

def run(app, **options)
conf = self.config(app, options)
conf = self.config(app, options)

log_writer = options.delete(:Silent) ? ::Puma::LogWriter.strings : ::Puma::LogWriter.stdio

launcher = ::Puma::Launcher.new(conf, :log_writer => log_writer)
launcher = ::Puma::Launcher.new(conf, :log_writer => log_writer, events: @events)

yield launcher if block_given?
begin
Expand Down
3 changes: 3 additions & 0 deletions test/config/event_on_booted.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
on_booted do
puts "on_booted called"
end
5 changes: 5 additions & 0 deletions test/config/event_on_booted_exit.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
on_booted do
pid = Process.pid
Process.kill :TERM, pid
Process.wait pid
end
10 changes: 10 additions & 0 deletions test/test_integration_cluster.rb
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,16 @@ def test_term_suppress
assert_equal 0, status
end

def test_on_booted
cli_server "-w #{workers} -C test/config/event_on_booted.rb -C test/config/event_on_booted_exit.rb test/rackup/hello.ru", no_wait: true

output = []

output << $_ while @server.gets

assert output.any? { |msg| msg == "on_booted called\n" } != nil
end

def test_term_worker_clean_exit
cli_server "-w #{workers} test/rackup/hello.ru"

Expand Down
10 changes: 10 additions & 0 deletions test/test_integration_single.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,16 @@ def test_term_exit_code
assert_equal 15, status
end

def test_on_booted
cli_server "-C test/config/event_on_booted.rb -C test/config/event_on_booted_exit.rb test/rackup/hello.ru", no_wait: true

output = []

output << $_ while @server.gets

assert output.any? { |msg| msg == "on_booted called\n" } != nil
end

def test_term_suppress
skip_unless_signal_exist? :TERM

Expand Down
33 changes: 33 additions & 0 deletions test/test_rack_handler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,39 @@
# RackUp#test_bin runs Puma using the rackup bin file
module TestRackUp
require "rack/handler/puma"
require "puma/events"

class TestOnBootedHandler < Minitest::Test
def app
Proc.new {|env| @input = env; [200, {}, ["hello world"]]}
end

def test_on_booted
on_booted = false
events = Puma::Events.new
events.on_booted do
on_booted = true
end

launcher = nil
thread = Thread.new do
Rack::Handler::Puma.run(app, events: events, Silent: true) do |l|
launcher = l
end
end

# Wait for launcher to boot
Timeout.timeout(10) do
sleep 0.5 until launcher
end
sleep 1.5 unless Puma::IS_MRI

launcher.stop
thread.join

assert_equal on_booted, true
end
end

class TestPathHandler < Minitest::Test
def app
Expand Down