我一直在Heroku上使用resque,它会不时用SIGTERM打断你的工作。
到目前为止,我已经用一个简单的处理了这个:
def process(options)
do_the_job
rescue Resque::TermException
self.defer options
end
我们已经开始使用resque-status以便我们可以跟踪作业,但是上面的方法显然打破了,因为当实际上它被推迟到另一个作业时,作业将显示完成。
我目前的想法是,不需要推迟resque中的当前作业,而是需要另一个作业重新排队因SIGTERM而失败的作业。
诀窍在于一些工作更复杂:
def process(options)
do_part1 unless options['part1_finished']
options['part1_finished']
do_part2
rescue Resque::TermException
self.defer options
end
简单地删除救援并简单地重试这些工作会在do_part1重复时导致异常。
答案 0 :(得分:0)
更深入地了解resque-status的工作原理,可能的解决方法是直接使用resque-status将使用的相同参数重新排队。
def process
do_part1 unless options['part1_finished']
options['part1_finished']
do_part2
rescue Resque::TermException
Resque.enqueue self.class, uuid, options
raise DeferredToNewJob
end
当然,这是未记录的,因此可能与未来的resque-status版本不兼容。
有一个缺点:在该工作失败和新工作捡起之间,第一个工作的状态将通过resque-status报告。 这就是为什么我重新提出一个新的例外 - 否则工作状态将显示完成,直到新工作人员拿起旧工作,这可能会混淆正在观看并等待工作完成的进程。
通过引发新的异常DeferredToNewJob,作业状态将暂时显示失败,这在前端更容易解决,并且可以从resque失败队列中自动清除特定异常。
<强>更新强>
resque-status为on_failure
处理程序提供支持。如果将具有此名称的方法定义为类的实例方法,我们可以使其更简单
这是我的on_failure
def on_failure(e)
if e.is_a? DeferredToNewJob
tick('Waiting for new job')
else
raise e
end
end
有了这个,这个工作基本上没有时间处于失败状态,因为进程看着它的状态。 此外,如果resque-status找到此处理程序,那么它不会将异常提升到resque,因此它不会被添加到失败的队列中。