Heroku等で運用しているとバッチサーバーを別のプロセスで実行するとお金が掛かったりするのでGoodJobを用いている場合にRailsアプリケーションと同一プロセスで起動する方法をメモ📝
GoodJobについてはこちら
やり方としては簡単で以下のようにgood_job.execution_modeを:asyncに変更するだけで大丈夫だった。
frozen_string_literal: true Rails.application.configure do config.good_job.queues = "*" - config.good_job.execution_mode = :external + config.good_job.execution_mode = :async config.good_job.cleanup_preserved_jobs_before_seconds_ago = 1.hour.to_i config.good_job.max_threads = 2 end
以下の通りexecution_modeを:asyncに設定するとRailsのアプリケーションプロセス内の別スレッドとして動作させることができるようです。また、consoleやmigration等で起動された場合には動作しないようになっているのもありがたいですね🙏
execution_mode(symbol) specifies how and where jobs should be executed. You can also set this with the environment variableGOOD_JOB_EXECUTION_MODE. It can be any one of:
:async(or:async_server) executes jobs in separate threads within the Rails web server 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:externalinstead. When not in the Rails web server, jobs will execute in:externalmode to ensure jobs are not executed withinrails console,rails db:migrate,rails assets:prepare, etc.
コードを軽く読んでみた限りですが、execution_modeを:asyncの場合にはRailsアプリケーションが起動されたタイミング(config.after_initialize)でGoodJob._start_async_adaptersが実行され、Railsアプリケーション内にGoodJobの各種機能が有効化され実行が開始され、
initializer "good_job.start_async" do config.after_initialize do ActiveSupport.on_load(:active_record) do ActiveSupport.on_load(:active_job) do GoodJob._framework_ready = true GoodJob._start_async_adapters end GoodJob._start_async_adapters end GoodJob._start_async_adapters end end end
エンキューされたタイミングで別スレッドを作って非同期で処理するようにしているようです。
def enqueue_at(active_job, timestamp) # ... executed_locally = execute_async? && @capsule&.create_thread(execution.job_state) Notifier.notify(execution.job_state) if !executed_locally && send_notify?(active_job)
※cronとかもどうなるのかなと思ったけどGoodJobの各種機能が有効化されるタイミングでCronのマネージャーも有効化されるからRailsアプリケーションの中でcronも動くようだった。
Solid Queueに移行しようかなと思っていたのですが、
Solid Queueでは現時点では以下で検討されてますが、まだ同一プロセスでの実行はできないっぽいですね👀
GoodJob便利!