1

私のアプリケーションに新しいUserを作成すると、after_createメソッドが実行され、Sidekiqワーカーが非同期にトリガーされます。Sidekiqがワーカーでオブジェクトを見つけることができません

この労働者...

def perform user_id 
    @user = ::User.find user_id 
    # ... 
end 

...常に次のエラーが返されます。

ActiveRecord::RecordNotFound: Couldn't find User with 'id'=315928979197048617

しかし、ユーザーID検索可能かどうかを確認するために、レールコンソールを使用して:

User.find(315928979197048617) 
=> #<User id: 315928979197048617> 

これは、t新しいユーザーの作成には時間がかかり、作業が終了したら既にそのメソッドを実行していますか?もし、その行動をどうやって修正すればよいでしょうか?

答えて

3

Active Recordのafter_createフックは、実際にレコードがデータベースに完全にコミットされる前に実際に実行されます。これにより、作業者スクリプトとデータベースの競合状態が発生し、その結果は作業者のエラーActiveRecord::RecordNotFoundになります(ただし、データベースがレースに勝った場合、すべてが計画どおりに実行されます)。

作業者がアクセスしようとする前にデータベースに保存されていることを確認するには、after_commitコールバックを使用する必要があります。作成時にこの操作を実行するだけなので、after_commit on: :createが必要です。

これは最後の問題を引き起こします。after_commitコールバックはテストで実行されないようです。これは、Railsがテストでトランザクションをラップし、テストトランザクションが実際にコミットされることがないため、コールバックが起動しないためです。 This blog post has a good write up on using after_commit、この問題を解決するにはtest_after_commit gemをお勧めします。

関連する問題