概要
実際に自分がエラーで困ったわけではありませんが、意識していないと怖いなと感じたので備忘録です
以下のようなissueがありました
どういうことかというと、
class User < ApplicationRecord
after_create -> { NotifyUserAfterCreate.perform_later(self) }
end
class NotifyUserAfterCreate < ApplicationJob
def perform(user)
puts "===== User created: #{user.inspect}"
end
end
createをフックして、ジョブにキューを入れている
app(dev)> User.create!
TRANSACTION (0.6ms) BEGIN
User Create (5.8ms) INSERT INTO `users` (`created_at`, `updated_at`) VALUES ('2024-12-14 10:54:29.078065', '2024-12-14 10:54:29.078065')
Enqueued NotifyUserAfterCreate (Job ID: 06f8e371-9a6d-4be9-98d1-bcd3054849d5) to Async(default) with arguments: #<GlobalID:0x0000ffff890aba98 @uri=#<URI::GID gid://app/User/146>>
↳ app/models/user.rb:2:in `block in <class:User>'
TRANSACTION (2.4ms) COMMIT
=> #<User:0x0000ffff8d352950 id: 146, created_at: "2024-12-14 10:54:29.078065000 +0000", updated_at: "2024-12-14 10:54:29.078065000 +0000">
User Load (0.7ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 146 LIMIT 1
Performing NotifyUserAfterCreate (Job ID: 06f8e371-9a6d-4be9-98d1-bcd3054849d5) from Async(default) enqueued at 2024-12-14T10:54:29.091801680Z with arguments: #<GlobalID:0x0000ffff8907d198 @uri=#<URI::GID gid://app/User/146>>
===== User created!!: #<User id: 146, created_at: "2024-12-14 10:54:29.078065000 +0000", updated_at: "2024-12-14 10:54:29.078065000 +0000">
Performed NotifyUserAfterCreate (Job ID: 06f8e371-9a6d-4be9-98d1-bcd3054849d5) from Async(default) in 3.74ms
ローカル環境では(ほとんどの場合)問題なく動く
実は問題がある
Jobのキューが実行されるタイミング次第で、
ActiveJob::DeserializationError: Error while trying to deserialize arguments: Couldn't find Task with 'id'=1
参考: https://qiita.com/kymmt90/items/470b9d2082e63d61b032
という例外が発生する
(自分のローカル環境でも2回だけ発生したが、再現できるだろうと思ってそのまま流したらその後再現できなくなってしまった)
issueによると、ジョブのキュー周りの処理が高速である本番環境で発生する問題らしい
開発環境で気付けないのは大変怖いので気をつけたい
Rails 7.2以降
トランザクションのコールバックを指定できるようになった
ActiveRecord::Base.transaction do |t|
user = User.create!
t.after_commit do
puts user.inspect
end
end
上記のようにCommit後の処理を指定できるようになった
Jobの場合はSerializerを通しているという強みがあったりするので、それぞれのプロジェクトでどちらを使うかを判断が必要そうです