TL;DR
Ruby on Rails で、バックグラウンドジョブを宣言し、キューイングのバックエンドで実行するためのフレームワーク。非同期処理に共通のインタフェースを提供する。
なぜ必要か
時間のかかる処理や急がない処理を、リクエストとレスポンスのサイクルから外に出せる。インタフェースが共通なので、ジョブのコードを変えずに、設定だけでバックエンドを切り替えられる。
仕組み
ジョブは app/jobs に ApplicationJob を継承したクラスとして置き、perform メソッドに処理を書く。bin/rails generate job <名前> で、クラスとテストのファイルを生成できる。
perform_later でジョブをキューに入れ、perform_now でその場で実行する。set(wait: ...) や set(wait_until: ...) を使うと、実行を遅らせられる。複数のジョブを一括でキューに入れるには perform_all_later を使う。
バックエンドは config.active_job.queue_adapter で選ぶ。Rails 8.0 からは、データベースを使う Solid Queue が既定である。ほかに Sidekiq、GoodJob、Resque なども使える。GlobalID の仕組みがあるので、Active Record のオブジェクトをそのまま perform の引数に渡せる。
例
class GuestsCleanupJob < ApplicationJob
queue_as :default
def perform(*guests)
# 後で実行したい処理
end
end
GuestsCleanupJob.set(wait: 1.week).perform_later(guest)注意点
- 既定では、失敗したジョブは再試行されない。再試行や破棄は
retry_onとdiscard_onで指定する。 - ActiveJob + Sidekiq で bulk queueing する によると、Sidekiq の
push_bulkやperform_bulkはSidekiq::Jobでしか使えず、Active Job から呼ぶと分かりにくいエラーになる。 - テストで使う
perform_enqueued_jobsは RSpec ではなく、Active Job のActiveJob::TestHelperが提供するメソッドである(RSpecについて最近話したことと自分のスタンス)。