从内部重新评估或评估延迟的工作?

有没有办法从作业任务本身内部确定正在运行的delayed_job作业的状态? 我有一个与服务相互作用的工作,这个服务非常不稳定,对于某类连接失败,我想要重新排队,只有在重试限制再次发生连接失败时才会引发exception。

伪代码来演示我想要做的事情:

def do_thing service.send_stuff(args) rescue Exception1, Exception2 if job.retries == JOBS_MAX raise else job.requeue end end 

我不想在任何失败时提出exception,因为通常这项工作将在以后的重试中完成,并且它只是为我制造噪音。 但我确实想知道它是否永远不会完成。

正如您所说,如果延迟作业运行器到达perform队列的末尾,那么它将被视为成功运行并从队列中删除。 所以你必须阻止它走到尽头。 没有重新排队 – 即使它是一个具有新属性的新记录。 因此,您可以重新考虑导致作业通知您exception的任何内容。 例如,您可以添加一个通知您的条件……

潜在解决方案

您可以使用Delayed::Worker.max_attempts获取默认的JOBS_MAX (使用伪编码),也可以通过定义方法来设置自己的每个作业,例如: max_attempts

 # Fail permanently after the 10th failure for this job def max_attempts 10 end 

也就是说,此方法可用于以下内容:

您还可以使用回调挂钩 。 如果定义了延迟作业,则会通过error方法回调您的有效负载对象。 因此,您可以使用error方法通知您超出给定尝试次数的实际exception。 要做到这一点…

在回调中,Delayed :: Job对象本身作为第一个参数返回:

 def error(job, exception) job.attempts # gives you the current attempt number # If job.attempts is greater than max_attempts then send exception notification # or whatever you want here... end 

因此,您可以使用回调开始添加逻辑,以便何时通知您自己以及何时不通知。 我甚至可能建议制作一组基本function,您可以将其包含在所有有效负载对象中以执行这些操作……但这取决于您和您的设计。

为DJ定义自定义作业,为max_attempts设置一个数字,并为error回调设置行为。 这是未经测试的,但它可能看起来像这样:

 class DoThingJob def max_attempts; @max_attempts ||= 5; end def error(job, exception) case exception when Exception1, Exception2 # will be requeued automatically until max_attempts is reached # can add extra log message here if desired else @max_attempts = job.attempts # this will cause DJ to fail the job and not try again end end end 

注意

在@pdobb发布他的回答之前我开始写这篇文章。 我还是发布它,因为它提供了一些关于如何处理exception和重新排队逻辑的更多细节。