I am using sidekiq to run some job after creating a record. when the job tries to find the record with the created ID, there are random cases where it raises a RecordNotFound
. how can this be possible?
class Person
def self.test_create
p = Person.create(
name: 'test'
)
p.run_on_sidekiq
end
def run_on_sidekiq
PersonJob.perform_async(self.id)
end
end
# Sidekiq runs on other server.
class PersonJob
def perform(id)
person = Person.find(id) # sometimes raises RecordNotFound!
# ...
# do something
# ...
end
end
EDIT: as per Alexei's answer, this case was more related with Sidekiq. edited the question to add more detail on Sidekiq usage.
This is a common case when you're using Sidekiq in after_create
hooks. What is actually going on is that Sidekiq starts working before the transaction has been finished, that's why it can't find model in database (and also because it's so blazingly fast). What you need to do is to change your after_create
hook to after_commit
which ensures that transaction has been finished.
If you show your exact code that uses Sidekiq, I can elaborate more about your specific usage.
UPDATE:
This is strange, your current code should be fine, since calling save/destroy
already gets wrapped in a transaction.
One reason I can think about is validation error. If your Person.create
call fails in some way, you'll get back an instance of Person
where id
would be nil
. This way, Sidekiq will try to find a record with id=nil
and will throw an error.
create
doesn't guarantee also it will roll-back silently, if there are any errors.
create!
would raise an exception
on failing condition.
What I would think the ideal way to call your method is to check if object is persisted?
against database.
def test_create
person = Person.create(name: 'test')
person.some_method if person.persisted?
end
Other way:
person.some_method unless person.errors.any?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With