TLDR:
把它放在你的工作方法的顶部:
begin
term_now = false
old_term_handler = trap 'TERM' do
term_now = true
old_term_handler.call
end
和
确保至少每十秒调用一次:
if term_now
puts 'told to terminate'
return true
end
和
在你的方法的最后,把这个:
ensure
trap 'TERM', old_term_handler
end
解释:
我遇到了同样的问题,并遇到了这篇 Heroku 文章。
该作业包含一个外部循环,因此我按照文章添加了一个trap('TERM')and exit。但是delayed_job ,将其捡起failed with SystemExit并将任务标记为失败。
现在SIGTERM被我们trap 的工人处理程序困住了,它不会被调用,而是立即重新启动作业,然后在SIGKILL几秒钟后得到。回到原点。
我尝试了一些替代方案exit:
我的最终解决方案是我的答案顶部给出的解决方案,它包括三个部分:
在我们开始可能很长的工作之前,我们'TERM'通过执行 a trap(如 Heroku 文章中所述)添加一个新的中断处理程序,并使用它来设置term_now = true.
但我们还必须抓住old_term_handler哪个延迟作业工人代码集(由 返回trap)并记住call它。
我们仍然必须确保我们Delayed:Job:Worker有足够的时间将控制权返回给它,以便它清理和关闭,所以我们应该term_now至少(略低于)每十秒检查一次,return如果它是true。
您可以return true或return false取决于您是否希望该工作被认为是成功的。
最后,重要的是要记住删除处理程序并Delayed:Job:Worker在完成后重新安装处理程序。如果你没有这样做,你将保留一个对我们添加的引用的悬空引用,如果你在其上添加另一个引用,这可能会导致内存泄漏(例如,当工作人员再次开始这项工作时)。