Rails の非同期処理を扱うとき、これまで delayd_job を使ってきました。
実行内容の保存先として SQL サーバー を使う delayd_job。
対して、実行内容の保存先に Redis を使う sidekiq といった様子のようです。
参考
sidekiq の導入
インストール
1 | gem 'redis-namespace' |
アクティブジョブとの連携
active_job の queue_adapter に sidekiq を登録します。
この辺りは delayed_job と同じ感じ。
1 | module App |
接続先 redis 設定
config/initializers/sidekiq.rb
に接続先の redis サーバーとクライアントの接続先を記述します。
(redis という名前で redis-server の起動しているホストを docker で用意してあります。)
1 | Sidekiq.configure_server do |config| |
sidekiq 設定
config/sidekiq.yml
を準備。
1 | :verbose: false |
ジョブの作成
次のコマンドでジョブを作成。
1 | rails generate job Hoge |
1 | class HogeJob < ApplicationJob |
sidekiq の起動
以下コマンドで、sidekiq を起動。
1 | bundle exec sidekiq -q default |
動作確認
動作確認したいので、app/jobs/hoge_job.rb
に確認用の記述を足します。
1 | class HogeJob < ApplicationJob |
Rails コンソールで HogeJob.perform_later
を実行すると以下のように sidekiq 側のコンソールに表示されます。
1 | 2021-04-25T09:39:03.718Z pid=595 tid=bpb class=HogeJob jid=37c61e2e607ce9e6879f6415 INFO: start |
遅延ジョブを呼び出すことができました。
遅延処理で ActiveRecord を書き換える
とりあえず実装
今度は sidekiq を使って遅延処理を行い、ActiveRecord のモデルの処理完了時刻を書き込んでみます。
こういうモデルがあるとします。
1 | class Item < ApplicationRecord |
こちらを遅延処理で呼び出してみます。
1 | class HogeJob < ApplicationJob |
次のように実行するとitem.task_end
が実行されて、時刻の書き込みがされます。
1 | i = Item.create |
ですが、mperham/sidekiq - Getting Startedには、以下の記述があります。
Your perform method arguments must be simple, basic types like String, integer, boolean that are supported by JSON. Complex Ruby objects will not work.
perform
メソッドの引数は、string
・integer
・bool
のような JSON によってサポートされている単純なタイプでなければなりません。複雑な Ruby オブジェクトは機能しないそうです。
ActiveRecord のオブジェクトは、単純なタイプとは言えないので、直してみます。
単純なオブジェクトを引数に実行させる
ID だけを渡して実行できるようにします。
1 | class HogeJob < ApplicationJob |
呼び出しは次のように変わります。
1 | i = Item.create |
単純な integer を渡すだけで遅延ジョブで ActiveRecord を書き換えできました。
一般化してみる
sidekiq のドキュメントに基づいて修正をしましたが、このままだと書き換えするモデルが変わる・増える度に、実装の修正・追加が必要になります。
実行内容を示す、クラス名、メソッド、対象の ID をすべてパラメーターで渡してみます。
1 | class HogeJob < ApplicationJob |
呼び出しは次のようになります。
1 | i = Item.create |
今回はシンプルにするため行っていませんが、クラスとして呼び出せるかのチェックの厳密化や、パラメータを拡張することもできます。
コールバック的に処理を呼び出すクラスとして切り出してしまうほうが、より利便性が高まると考えます。
sidekiq を使ってみました。
遅延ジョブの処理は今まで delayd_job を使ってきましたが、1 つ所にこだわらないようしたいところです。.delay
で呼び出せば良かった delayd_job と比べれば、何を遅延ジョブにしたいのか設計するというステップがしっかり必要そうです。
ではでは。