socketry / falcon

A high-performance web server for Ruby, supporting HTTP/1, HTTP/2 and TLS.
https://socketry.github.io/falcon/
MIT License
2.66k stars 82 forks source link

Provide an example falcon.rb setup for Rails (migrating from Puma) #189

Closed johnnyshields closed 7 months ago

johnnyshields commented 2 years ago

To save time and ease migration, it would be good to have a simple migration guide for users like myself coming from Puma. It would be super-useful to have a guide saying "If you use option X in puma.rb, here's how you do it with option Y in falcon.rb."

Here's Rails' default puma.rb and here's my own puma.rb, which is enables a few more standard options.

#!/usr/bin/env puma
# frozen_string_literal: true

environment ENV.fetch('RAILS_ENV', 'development')

workers ENV.fetch('WEB_CONCURRENCY', 0).to_i

threads_count = ENV.fetch('RAILS_MAX_THREADS', 5).to_i
threads threads_count, threads_count

bind "tcp://#{ENV.fetch('HTTP_LISTEN_ADDRESS', '0.0.0.0')}:#{ENV.fetch('HTTP_LISTEN_PORT', '9292')}"

activate_control_app 'tcp://0.0.0.0:9293', no_token: true

raise_exception_on_sigterm false

fork_worker

prune_bundler

nakayoshi_fork if RUBY_VERSION >= '2.7.0'

wait_for_less_busy_worker

before_fork do
  Mongoid.disconnect_clients
end

if ENV.fetch('RAILS_ENV', 'development') == 'development'
  worker_timeout 3600
  pidfile ENV.fetch('PIDFILE', 'tmp/pids/server.pid')
  plugin :tmp_restart
end
trevorturk commented 1 year ago

I left some related notes here for others that might be looking: https://github.com/socketry/falcon/issues/121

My current setup for a Rails app running on Heroku looks like this:

Procfile:

web: bundle exec ./falcon.rb

falcon.rb

#!/usr/bin/env -S falcon host

load :rack

hostname = File.basename(__dir__)
port = ENV["PORT"] || 3000

rack hostname do
  append preload "preload.rb"
  cache false
  count ENV.fetch("FALCON_COUNT", 1).to_i
  endpoint Async::HTTP::Endpoint.parse("http://0.0.0.0:#{port}").with(protocol: Async::HTTP::Protocol::HTTP11)
end

preload.rb

require_relative "config/environment"

...this doesn't cover all of the options in that example Puma config, but it might be a start if someone is migrating from Puma to Falcon, I'm sure a PR with documentation/guide content would be most welcome!

joeldrapper commented 1 year ago

I followed the current Rails guide on a brand new Rails install and immediately ran into this error.

               | Task may have ended with unhandled exception.
               |   Concurrent::IllegalOperationError: Cannot release a read lock which is not held
               |   → /Users/joeldrapper/.rbenv/versions/3.2.1/lib/ruby/gems/3.2.0/gems/concurrent-ruby-1.2.2/lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb:246 in `release_read_lock'
               |     /Users/joeldrapper/.rbenv/versions/3.2.1/lib/ruby/gems/3.2.0/gems/actionview-7.0.4.3/lib/action_view/cache_expiry.rb:21 in `complete'
               |     /Users/joeldrapper/.rbenv/versions/3.2.1/lib/ruby/gems/3.2.0/gems/activesupport-7.0.4.3/lib/active_support/execution_wrapper.rb:37 in `before'
               |     /Users/joeldrapper/.rbenv/versions/3.2.1/lib/ruby/gems/3.2.0/gems/activesupport-7.0.4.3/lib/active_support/callbacks.rb:423 in `block in make_lambda'
               |     /Users/joeldrapper/.rbenv/versions/3.2.1/lib/ruby/gems/3.2.0/gems/activesupport-7.0.4.3/lib/active_support/callbacks.rb:199 in `block (2 levels) in halting'
               |     /Users/joeldrapper/.rbenv/versions/3.2.1/lib/ruby/gems/3.2.0/gems/activesupport-7.0.4.3/lib/active_support/callbacks.rb:687 in `block (2 levels) in default_terminator'
               |     /Users/joeldrapper/.rbenv/versions/3.2.1/lib/ruby/gems/3.2.0/gems/activesupport-7.0.4.3/lib/active_support/callbacks.rb:686 in `catch'
               |     /Users/joeldrapper/.rbenv/versions/3.2.1/lib/ruby/gems/3.2.0/gems/activesupport-7.0.4.3/lib/active_support/callbacks.rb:686 in `block in default_terminator'
               |     /Users/joeldrapper/.rbenv/versions/3.2.1/lib/ruby/gems/3.2.0/gems/activesupport-7.0.4.3/lib/active_support/callbacks.rb:200 in `block in halting'
               |     /Users/joeldrapper/.rbenv/versions/3.2.1/lib/ruby/gems/3.2.0/gems/activesupport-7.0.4.3/lib/active_support/callbacks.rb:595 in `block in invoke_before'
               |     /Users/joeldrapper/.rbenv/versions/3.2.1/lib/ruby/gems/3.2.0/gems/activesupport-7.0.4.3/lib/active_support/callbacks.rb:595 in `each'
               |     /Users/joeldrapper/.rbenv/versions/3.2.1/lib/ruby/gems/3.2.0/gems/activesupport-7.0.4.3/lib/active_support/callbacks.rb:595 in `invoke_before'
               |     /Users/joeldrapper/.rbenv/versions/3.2.1/lib/ruby/gems/3.2.0/gems/activesupport-7.0.4.3/lib/active_support/callbacks.rb:106 in `run_callbacks'
               |     /Users/joeldrapper/.rbenv/versions/3.2.1/lib/ruby/gems/3.2.0/gems/activesupport-7.0.4.3/lib/active_support/execution_wrapper.rb:143 in `complete'
               |     /Users/joeldrapper/.rbenv/versions/3.2.1/lib/ruby/gems/3.2.0/gems/activesupport-7.0.4.3/lib/active_support/execution_wrapper.rb:137 in `complete!'
               |     /Users/joeldrapper/.rbenv/versions/3.2.1/lib/ruby/gems/3.2.0/gems/actionpack-7.0.4.3/lib/action_dispatch/middleware/executor.rb:15 in `block in call'
               |     /Users/joeldrapper/.rbenv/versions/3.2.1/lib/ruby/gems/3.2.0/gems/rack-2.2.6.4/lib/rack/body_proxy.rb:29 in `close'
               |     /Users/joeldrapper/.rbenv/versions/3.2.1/lib/ruby/gems/3.2.0/gems/protocol-rack-0.2.4/lib/protocol/rack/body/enumerable.rb:58 in `close'
               |     /Users/joeldrapper/.rbenv/versions/3.2.1/lib/ruby/gems/3.2.0/gems/protocol-http-0.24.1/lib/protocol/http/body/wrapper.rb:32 in `close'
               |     /Users/joeldrapper/.rbenv/versions/3.2.1/lib/ruby/gems/3.2.0/gems/protocol-http-0.24.1/lib/protocol/http/body/deflate.rb:36 in `close'
               |     /Users/joeldrapper/.rbenv/versions/3.2.1/lib/ruby/gems/3.2.0/gems/async-http-0.60.1/lib/async/http/protocol/http2/output.rb:109 in `passthrough'
               |     /Users/joeldrapper/.rbenv/versions/3.2.1/lib/ruby/gems/3.2.0/gems/async-2.5.0/lib/async/task.rb:158 in `block in run'
               |     /Users/joeldrapper/.rbenv/versions/3.2.1/lib/ruby/gems/3.2.0/gems/async-2.5.0/lib/async/task.rb:310 in `block in schedule'
ioquatix commented 1 year ago

This will be fixed in Rails 7.1

Rails 7.0 is incompatible.