Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails関連

Rails 7.1: 複数ジョブを一度にエンキューするperform_all_laterが追加(翻訳)

概要

元サイトの許諾を得て翻訳・公開いたします。

日本語タイトルは内容に即したものにしました。

参考: 週刊Railsウォッチ20230314: 複数ジョブを一度にエンキューするperform_all_laterが追加

Rails 7.1: 複数ジョブを一度にエンキューするperform_all_laterが追加(翻訳)

このブログ記事はRails 7シリーズの一環です。

Rails 7.1に、複数のジョブを一度にエンキューするActiveJob.perform_all_laterメソッドが追加されました。このメソッドはジョブインスタンスの配列を受け取ります。Active Recordのバルク系メソッドと同様に、perform_all_laterもコールバックを実行しません。

たとえば、メールを複数ユーザーに送信したい場合は以下のように書けます。

welcome_email_jobs = users.map do |user|
  WelcomeEmailJob.new(user)
end

ActiveJob.perform_all_later(welcome_email_jobs)

perform_all_laterを使うことで、usersのレコードをループで処理してからperform_laterを実行するよりも、キューデータストアへのラウンドトリップ回数を減らせます。つまり、キューイングバックエンドがSidekiqの場合は、Redisのラウンドトリップのレイテンシを削減できます。
PostgreSQLを利用するGoodJobなどをキューイングバックエンドに使っている場合は、perform_all_laterですべてのジョブが1個のINSERT文でエンキューされるので、パフォーマンスがさらに高まります。

ただし、キューイングバックエンドがバルク(一括)エンキューをサポートしていない場合は、個別のジョブをエンキューする形にフォールバックするのでご注意ください。

Active Jobはさまざまなジョブ処理ライブラリの違いを抽象化するよう設計されているので、インターフェイスが統一されています。このしくみは、Active Jobがサポートしている多くのアダプタによって実現されています。

キューイングバックエンドの中でも人気の高いSidekiqでは、push_bulkメソッドがすでにサポートされています。プルリク#46603の作者は、Sidekiqアダプタを変更することでこのperform_all_laterメソッドでSidekiqのpush_bulkメソッドを利用可能にしました。

なお、最近GoodJobにもバルクキューイング機能が追加されました(#790)。

bensheldon/good_job - GitHub

実際のActiveJob.perform_all_laterが有用なのは、数千件ものジョブを一度にキューに流し込みたい場合のみです。一度にエンキューするジョブ数が少ない場合、パフォーマンス上のメリットはさほどありません。

詳しくは#46603をご覧ください。

関連記事

Rails: Active Jobスタイルガイド(翻訳)

Rails: SidekiqはActive Jobを経由せずに直接使おう(翻訳)


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。