rails sidekiq 找不到创建的记录

Yeo*_*nho 5 ruby mysql ruby-on-rails sidekiq ruby-on-rails-4

创建记录后,我正在使用 sidekiq 运行一些作业。当作业尝试使用创建的 ID 查找记录时,在随机情况下它会引发RecordNotFound. 这怎么可能?

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
Run Code Online (Sandbox Code Playgroud)

编辑:根据Alexei的回答,这个案例与 Sidekiq 更相关。编辑了问题以添加有关 Sidekiq 用法的更多详细信息。

Ale*_*ein 8

当您after_create钩子中使用 Sidekiq时,这是一种常见情况。实际发生的事情是 Sidekiq 在事务完成之前就开始工作,这就是为什么它在数据库中找不到模型的原因(也因为它非常快)。你需要做的是改变你的after_create钩子,after_commit以确保事务已经完成。

如果您显示使用 Sidekiq 的确切代码,我可以详细说明您的具体用法。

更新:这很奇怪,您当前的代码应该没问题,因为调用save/destroy已经包含在事务中。

我能想到的一个原因是验证错误。如果您的Person.create调用以某种方式失败,您将返回Personwhere idwould be的实例nil。这样,Sidekiq 将尝试查找记录id=nil并抛出错误。


Nit*_*hin 1

create如果出现任何错误,也不保证它会默默地回滚。

create!会提出exception失败条件。

我认为调用方法的理想方法是检查对象是否persisted?针对数据库。

 def test_create
   person = Person.create(name: 'test')
   person.some_method if person.persisted?
 end
Run Code Online (Sandbox Code Playgroud)

另一种方式:

person.some_method unless person.errors.any?
Run Code Online (Sandbox Code Playgroud)