0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ひとりアドベントカレンダーAdvent Calendar 2024

Day 14

【Rails】after_createでJobにキューを入れると本番環境でエラーになることがある

Last updated at Posted at 2024-12-14

概要

実際に自分がエラーで困ったわけではありませんが、意識していないと怖いなと感じたので備忘録です

以下のようなissueがありました

どういうことかというと、

user.rb
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回だけ発生したが、再現できるだろうと思ってそのまま流したらその後再現できなくなってしまった:cry:

issueによると、ジョブのキュー周りの処理が高速である本番環境で発生する問題らしい

開発環境で気付けないのは大変怖いので気をつけたい

Rails 7.2以降

トランザクションのコールバックを指定できるようになった

ActiveRecord::Base.transaction do |t|
    user = User.create!

    t.after_commit do
        puts user.inspect
    end
end

上記のようにCommit後の処理を指定できるようになった

Jobの場合はSerializerを通しているという強みがあったりするので、それぞれのプロジェクトでどちらを使うかを判断が必要そうです

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?