【问题标题】:Sidekiq not finding object in workerSidekiq 在工作人员中找不到对象
【发布时间】:2018-01-02 10:39:40
【问题描述】:

当我在我的应用程序中创建一个新的User 时,我运行一个after_create 方法,然后异步触发一个 Sidekiq 工作器。

这个工人...

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

...总是返回以下错误:

ActiveRecord::RecordNotFound: 找不到 'id'=315928979197048617 的用户

但使用 rails 控制台检查用户 id 是否可找到:

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

这是因为新用户的创建需要一些时间并且工作人员在完成时已经执行了该方法吗?如果,我将如何解决这种行为?

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-5 backgroundworker sidekiq


    【解决方案1】:

    您说的完全正确,Active Record 中的after_create 挂钩实际上是在记录完全提交到数据库之前运行的。这会导致您的工作脚本和数据库出现竞争条件,其结果是工作人员中的ActiveRecord::RecordNotFound 错误(尽管如果数据库赢得比赛,那么一切似乎都按计划进行)。

    为确保您的用户在您的工作人员尝试访问它之前已保存到数据库中,您应该使用after_commit 回调。由于您只是在创建时执行此操作,因此您需要after_commit on: :create

    这确实导致了最后一个问题,after_commit 回调似乎从未在测试中运行。这是因为 Rails 将测试包装在事务中,并且测试事务从未真正提交,因此不会触发回调。 This blog post has a good write up on using after_commit 并推荐 test_after_commit gem 来解决这个问题。

    【讨论】:

      猜你喜欢
      • 2013-07-10
      • 2018-11-05
      • 2015-01-03
      • 2012-10-05
      • 1970-01-01
      • 2012-07-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多