Rails ActiveJob - 如何阻止作业在 before_enqueue 中排队
Posted
技术标签:
【中文标题】Rails ActiveJob - 如何阻止作业在 before_enqueue 中排队【英文标题】:Rails ActiveJob - how to stop job from being enqueued in before_enqueue 【发布时间】:2017-09-10 20:54:54 【问题描述】:我正在运行 Rails 4.2.8,我想让我的工作只在特定条件下运行。目前我正在检查调用作业的代码,但在作业类中包含逻辑会更清晰。有没有人这样做过?
class MyJob < ApplicationJob
before_enqueue do |job|
# check and stop job from being enqueued under certain conditions
end
def perform(args*)
# code here
end
end
我使用 Sidekiq 4.2.10 作为后台作业适配器。
【问题讨论】:
【参考方案1】:throw :abort
从您的before_enqueue
停止执行回调链和perform
。
代码:https://github.com/rails/rails/blob/fc20050ea69ba3b8d8bc90171d2dcbf93e9a1dae/activesupport/lib/active_support/callbacks.rb#L23
【讨论】:
我尝试在before_enqueue
中引发异常并使用discard_on
,但没有成功。异常没有被捕获,它正在停止代码的执行。所以你的解决方案不起作用@Sergio。如果在 before_perform 回调中引发异常,则引发异常和丢弃将起作用。可能是因为 before_enqueue 是在将作业入队的同一进程中运行的,但 before_perform 是在 sidekiq worker 中运行的。
Rails 存储库中的测试似乎表明 throw
-ing 和 exception
(不要在 Ruby 中与 raise
-ing 和 error
混淆):abort
它将停止工作的排队。 github.com/rails/rails/blob/…
@Adeynack :abort
也不例外
@SergioTulentsev:用 Ruby 术语来说是这样。例外是符号。见coderwall.com/p/lhkkug/…
@Adeynack:是的,听起来更像。 :+1:【参考方案2】:
您可以使用around_enqueue
来获得相同的结果而不会引发异常。当您的工作期望不排队时,这可能很有用。
例如:
around_enqueue do |_job, block|
if my_condition
block.call # this will enqueue your job
end
end
OBS:值得注意的是,此答案基于 Rails 5 ActiveJob 代码,但也必须适用于 Rails 4。
【讨论】:
我认为使用 around_enqueue 是在将作业添加到队列之前取消作业的唯一选项。我尝试将 before_enqueue 与 discard_on 结合使用,但没有奏效。未捕获异常,它正在停止执行正在排队作业的进程中的代码。以上是关于Rails ActiveJob - 如何阻止作业在 before_enqueue 中排队的主要内容,如果未能解决你的问题,请参考以下文章
如何将自定义的延迟作业作业与 ActiveJob 一起使用?