-
-
Notifications
You must be signed in to change notification settings - Fork 204
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 async_server
option to run async only in Rails web server process
#230
Conversation
…ss; renames `async` option to `async_all` with deprecation notice
@tedhexaflow Could you please review this change to I think this PR will be a good change by removing some of the rough edges of async mode running in unexpected places. |
Hi @bensheldon, Thanks for the heads up. Let me do a test and get back to you. |
Hi @bensheldon I've checked, and Rails.const_defined?("Server") will return false if we run the app on tomcat. So if I need to continue using async mode on tomcat, I will have to use async_all, and async_server won't work. Am I right? |
@tedhexaflow Thank you for checking! That's a bummer. I would really like to make this PR work for Tomcat/jRuby before moving forward. Is there a blog post/instructions that you would recommend for me to simulate/recreate a jRuby/Tomcat server setup? Or could you list out the tools you're using? (I hate to ask you to do too much work). |
Hi @bensheldon In addition to JDK 15*, JRuby-9.2*, We need warbler https://github.com/jruby/warbler to bundle the rails app into a war file. Then download tomcat https://tomcat.apache.org/download-90.cgi and start the tomcat server by running bin/startup.sh. (the server will run on port 8080. you can change them in conf/server.xml) Copy the war file to webapps/ROOT.war and open http://localhost:8080. This link looks a little outdated, but I had a quick look, and we can still use it for a reference. I wish I could have a docker image ready to provide you. Unfortunately, I didn't create one before. In case setting up the tomcat wasting too much of your time and if you can wait a bit longer, I'll try to create a docker image for you next week. Or you can try to set it up, and if you need help, please feel free to ask, and I will try my best to help. Cheers! |
@tedhexaflow that's all super helpful. I will try to get that running in a Docker file. Really specifically, what I'm looking for is a way to determine, in the Ruby code, "Is the current ruby process running as a webserver or not?" With MRI it seems as simple as checking |
Hi @bensheldon To clarify, Rails.const_defined?("Server") will return TRUE for both MRI and JRuby while running on Puma Server. But running on Tomcat will not return TRUE. |
Hi @bensheldon I've also ask help from Charles from JRuby. |
@tedhexaflow thank you! I'll add some more details to jruby/jruby#6657 |
Having done some experimentation, I think the proper logic is: def in_server_process?
Rails.const_defined?('Server') ||
caller.grep(%r{config.ru}).any? || # config.ru:3:in `block in <main>' OR config.ru:3:in `new_from_string'
(Concurrent.on_jruby? && caller.grep(%r{jruby/rack/rails_booter}).any? # uri:classloader:/jruby/rack/rails_booter.rb:83:in `load_environment'
end Some experimental information: MRI
JRuby
What I didI've added this code to puts "== DEBUGGING =="
puts "Rails::Server=#{Rails.const_defined?('Server')}"
puts "JRuby::Rack=#{defined?(JRuby) && JRuby.const_defined?('Rack')}"
puts "config.ru=#{caller.grep(%r{config.ru}).any?}"
puts "jruby/rack/rails_booter=#{caller.grep(%r{jruby/rack/rails_booter}).any?}" # uri:classloader:/jruby/rack/rails_booter.rb:83:in `load_environment'
# puts "CALLER: \n #{caller.join("\n ")}"
puts "== /DEBUGGING ==" MRI# Running the Web Server
$ bin/rails server
# Rails::Server=true
# JRuby::Rack=
# config.ru=false
# jruby/rack/rails_booter=false
# Running a rack app directly
$ bundle exec puma -C config/puma.rb config.ru
# Rails::Server=false
# JRuby::Rack=
# config.ru=true
# jruby/rack/rails_booter=false
# Running a Rake Task
$ bin/rails db:create
# Rails::Server=false
# JRuby::Rack=
# config.ru=false
# jruby/rack/rails_booter=false
# Running a generator
$ bin/rails g migration ExampleTestMigration
# Rails::Server=false
# JRuby::Rack=
# config.ru=false
# jruby/rack/rails_booter=false
JRuby# Building a WAR with Warbler
$ MAVEN_REPO=https://repo1.maven.org/maven2 bundle exec warble runnable executable war
# Rails::Server=false
# JRuby::Rack=true
# config.ru=false
# jruby/rack/rails_booter=false
# Running the Web Server
$ java -jar good_job_jruby_experiments.war
Rails::Server=false
JRuby::Rack=true
config.ru=false
jruby/rack/rails_booter=true
# Running a Rake Task
$ java -jar good_job_jruby_experiments.war -S rails db:create
# Rails::Server=false
# JRuby::Rack=true
# config.ru=false
# jruby/rack/rails_booter=false
# Running a generator
$ java -jar good_job_jruby_experiments.war -S rails g migration ExampleTestMigration
# Rails::Server=false
# JRuby::Rack=true
# config.ru=false
# jruby/rack/rails_booter=false |
async_server
option to run async only in Rails web server process; renames async
option to async_all
with deprecation noticeasync_server
option to run async only in Rails web server process
d876d5d
to
512406f
Compare
8d1eb0f
to
6b8a063
Compare
Closes #194.
:async_server
executes jobs in separate threads within the Rails webserver process (bundle exec rails server
). It can be more economical for small workloads because you don’t need a separate machine or environment for running your jobs, but if your web server is under heavy load or your jobs require a lot of resources, you should choose:external
instead. When not in the Rails webserver, jobs will execute in:external
mode to ensure jobs are not executed withinrails console
,rails db:migrate
,rails assets:prepare
, etc.On second thought,:async_all
executes jobs in all Rails processes. (Previously this configuration option was:async
, which is deprecated. In future versions:async
will behave like:async_server
).async
is not deprecated. This PR just adds a new option, and doesn't change the previous config behavior.