我一直在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被重复时,简单地删除救援并简单地重试这些作业将导致异常。
发布于 2017-02-02 23:46:41
更深入地了解resque-status是如何工作的,一种可能的解决方法是使用resque-status将使用的相同参数直接转到resque以重新排队。
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报告。这就是我重新引发一个新异常的原因--否则,作业状态将显示为已完成,直到新的worker接过旧作业,这可能会混淆正在监视和等待作业完成的进程。
通过引发新的异常DeferredToNewJob,作业状态将临时显示失败,这更容易在前端解决,并且可以自动从重新排队失败队列中清除特定的异常。
更新
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,因此它不会被添加到失败的队列中。
https://stackoverflow.com/questions/41991885
复制相似问题