はじめに
非同期処理導入時につまづいたところをまとめる。
本題
その1
トランザクション内でジョブをenqueueすると、コミット前にワーカーが動いてしまう。
コミット前のためまだDB上にそのレコードが存在せず、ctiveJob::DeserializationError: Error while trying to deserialize arguments: Couldn't find ... with 'id'=... というデシリアライズエラーになる。
対応としては、非同期処理を呼び出す処理自体を、トランザクションの外に出す。
その2
Redisを複数アプリ・複数環境で共有している場合、DB番号やキュー名で名前空間を分けないと混線する。
全てのコンテナに同じ環境変数をセットする
Web側には REDIS_DB が設定されていたが、Sidekiqワーカー側に未設定だと動かないので、ワーカー側にも同じ環境変数を設定する
{ "name": "REDIS_DB", "value": "1" }
環境変数でキュー名にprefixをつけ、環境ごとに分離する
同じRedis・同じキュー名を複数環境で共有していたため、環境Aのジョブを環境Bのワーカーが拾ってしまう。DB番号の分離漏れと同根の問題。
アプリや環境ごとに分ける。
queue_prefix = ENV.fetch("SIDEKIQ_QUEUE_PREFIX", "")
Sidekiq.configure_server do |config|
config[:queues] = ["#{queue_prefix}default"]
end
まとめ
よくある事例だと思うが、基本なので気をつけたい