【问题标题】:rails sidekiq cannot find the created recordrails sidekiq 找不到创建的记录
【发布时间】:2015-11-09 07:06:48
【问题描述】:

我在创建记录后使用 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 使用的更多详细信息。

【问题讨论】:

  • 您找到解决方案了吗?我遇到了同样的问题!我将 ID 传递给 Sidekiq 工作人员,并且该 ID 确实适用于工作人员外部的查询,而不是工作人员内部的查询。

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


【解决方案1】:

当你是using Sidekiq in after_create 钩子时,这是一个常见的情况。实际上发生的事情是 Sidekiq 在事务完成之前开始工作,这就是它无法在数据库中找到模型的原因(也因为它非常快)。您需要做的是将您的after_create 挂钩更改为after_commit,以确保事务已完成。

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

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

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

【讨论】:

  • 我已编辑问题以添加更多详细信息。但是,我没有使用 after_create 钩子。创建返回后,我将颁发的 ID 发送到 sidekiq。使用after_commit 是确保记录已创建的唯一方法吗?
【解决方案2】:

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?

【讨论】:

    猜你喜欢
    • 2019-01-24
    • 2013-08-09
    • 1970-01-01
    • 2014-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多