ActiveJob 在“测试”环境中找不到记录

ActiveJob could not find record in `test` environment

此问题仅存在于 test 环境中。在 development 环境下一切正常。

最近从 Rails 4.2.7.1 升级到 Rails 5.0.0.1 后,我遇到了一个奇怪的问题。升级前一切正常。

在我的一个模型中,我使用 ActiveJob 来执行任务。

# webhook_invocation.rb

def schedule_invocation
  WebhookRequestJob.perform_later(id)
end

def init
  remember_webhook # No DB changes
  init_errors_context # No DB changes
  flow_step_invocation.implementation = self
  flow_step_invocation.save!

  return unless calculate_expressions  # No DB changes
  calculated! # An AASM event, with no callbacks
  schedule_invocation
end

并在 WebhookRequestJob#perform 中,我使用提供的 ID 检索对象

# webhook_request_job.rb

def perform(webhook_invocation_id)
  invocation = WebhookInvocation.find_by(id: webhook_invocation_id)
  invocation.run_request
end

问题是在#perform中找不到记录(invocation变成nil)。我什至尝试将 p WebhookInvocation.all 作为第一行,但它打印的只是一个空集合。另一方面,如果我在 #schedule_invocation 方法中尝试 p WebhookInvocation.all,它会正确打印出 WebhookInvocation.

的所有对象

没有引发异常,也没有警告行。

编辑 1:

我什至尝试将对象直接传递给 #perform_later,即 WebhookRequestJob.perform_later(self),但在 #perform 处接收到的对象是 nil

编辑 2:

我注意到有一些像 Creating scope :fail. Overwriting existing method FlowStepInvocation.fail 这样的消息是由使用 AASM 引起的。我使用 create_scopes: false 消除了它们。但是还是没有解决问题。

根据您提供的信息,我猜测您在 after_saveafter_create 回调中调用了 schedule_invocation 方法。由于回调被调用,ActiveJob 可能甚至在对象实际持久化之前(在 COMMIT 完成之前)就开始处理作业。在这种情况下,处理作业时您的记录将不会显示在数据库中,您将得到一个空集合或 nil

要解决此问题,请将回调更改为 after_commit 以确保 COMMIT 操作在您将作业排队之前发生。

原来config.active_job.queue_adapter在Rails5之前默认设置为:inline,但在Rails5中设置为:async

这使规格失效(不知道为什么)。为了解决这个问题,我在 config/environments/test.rb:

中添加了以下行
config.active_job.queue_adapter = :inline