bensheldon / good_job

Multithreaded, Postgres-based, Active Job backend for Ruby on Rails.

Home Page:https://goodjob-demo.herokuapp.com/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Good job is running with standalone action cable server

AlfonsoUceda opened this issue · comments

Hi folks!

Thank you for this amazing gem. I'm starting the migration from delayed job to good job and I've found a weird issue when running a standalone action cable server.

This is the config.ru I have and I've configured good job as external in production environment.

require_relative "../config/environment"
Rails.application.eager_load!

run ActionCable.server

when I run the following command I get good job running and this is a side effect I don't want.

 SECRET_KEY_BASE=1 RAILS_ENV=production bundle exec puma -p 28080 cable/config.ru

I've also configured puma as suggested in the README file.

After debugging a bit I've seen the following method that is invoked from puma.rb file

  def self.restart(timeout: -1)
    return if configuration.execution_mode != :async && configuration.in_webserver?

    _shutdown_all(Capsule.instances, :restart, timeout: timeout)
  end

And I see that the execution_mode is external but the in_webserver? is false so that's why good job starts.

Is this intended? If configured with external execution mode shouldn't run as async.

Hmmm. My simple answer is that you probably should not GoodJob.restart in puma.rb if you don't want to start GoodJob. I imagine you could do something like:

# cable/config.ru
ENV["ACTIONCABLE_SERVER"] = 1
require_relative "../config/environment"
Rails.application.eager_load!

run ActionCable.server

# config/puma.rb
#...
  GoodJob.restart unless ENV["ACTIONCABLE_SERVER"]

I do wonder if it would work as expected if you ran it through the bin/rails server command e.g.:

SECRET_KEY_BASE=1 RAILS_ENV=production bin/rails server -p 28080 -c cable/config.ru

...because that would cause the Rails::Server constant to be defined and thus the configuration.in_webserver? to be more accurate. I also wonder if you have suggestions for improving the detection from within a webserver?

@_in_webserver = Rails.const_defined?(:Server) || begin
self_caller = caller
self_caller.grep(%r{config.ru}).any? || # EXAMPLE: config.ru:3:in `block in <main>' OR config.ru:3:in `new_from_string'
self_caller.grep(%r{puma/request}).any? || # EXAMPLE: puma-5.6.4/lib/puma/request.rb:76:in `handle_request'
self_caller.grep(%{/rack/handler/}).any? || # EXAMPLE: iodine-0.7.44/lib/rack/handler/iodine.rb:13:in `start'
(Concurrent.on_jruby? && self_caller.grep(%r{jruby/rack/rails_booter}).any?) # EXAMPLE: uri:classloader:/jruby/rack/rails_booter.rb:83:in `load_environment'
end || false

@bensheldon thank you for your answer. I did what you suggested but finally I've decided to run good job in a separate process for development environment and get rid the config from puma file.

Why does configuration.in_webserver? exist? Isn't it enough to use configuration.execution_mode != :async?

btw, I just reverted a recent change that might make this better for you: https://github.com/bensheldon/good_job/releases/tag/v3.27.3

Thanks @bensheldon

I will close the issue anyway ;)