Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sidekiq not finding object in worker

When I create a new User in my app, I run an after_create method which then asynchronously triggers a Sidekiq worker.

This worker ...

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

... always returns the following error:

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

But using the rails console to check if the User id findable:

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

Does this happen because the creation of the new User takes some time and the worker has already performed the method when finished? If, how would I fix that behavior?

like image 745
heroxav Avatar asked Oct 20 '25 13:10

heroxav


1 Answers

You are absolutely right, the after_create hook in Active Record actually runs before the record is fully committed to the database. This causes a race condition with your worker script and the database, the results of which are ActiveRecord::RecordNotFound errors in the worker (though if the database wins the race then everything seems to go as planned).

To ensure that your user has been saved to the database before your worker tries to access it, you should use the after_commit callback. Since you are only performing this operation on creation, you need after_commit on: :create.

This does cause one last problem, after_commit callbacks never seem to run under testing. This is because Rails wraps tests in transactions and the test transaction is never actually committed so the callback doesn't fire. This blog post has a good write up on using after_commit and recommends the test_after_commit gem to overcome this issue.

like image 136
philnash Avatar answered Oct 22 '25 02:10

philnash



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!