rails sidekiq无法找到创建的记录

时间:2015-11-09 07:06:49

标签: mysql ruby-on-rails ruby ruby-on-rails-4 sidekiq

我在创建记录后使用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

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

2 个答案:

答案 0 :(得分:1)

create并不保证如果有任何错误,它也会以静默方式回滚。

create!会因失败而提出exception

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

 def test_create
   person = Person.create(name: 'test')
   person.some_method if person.persisted?
 end

其他方式:

person.some_method unless person.errors.any?

答案 1 :(得分:1)

这是您using Sidekiq in after_create挂钩的常见情况。实际上是Sidekiq在交易完成之前开始工作,这就是为什么它无法在数据库中找到模型(也因为它的速度非常快)。您需要做的是将after_create挂钩更改为after_commit,以确保交易已完成。

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

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

我能想到的一个原因是验证错误。如果您的Person.create来电以某种方式失败,那么您将获得Person id nil id=nil的实例。这样,Sidekiq将尝试使用NSLayoutConstraint查找记录,并将抛出错误。