首页 文章

Sidekiq没有找到 Worker 的对象

提问于
浏览
2

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

这个 Worker ......

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

...始终返回以下错误:

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

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

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

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

1 回答

  • 4

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

    要确保在工作程序尝试访问之前将用户保存到数据库,应使用 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来克服这个问题 .

相关问题