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

时间:2014-05-20 17:26:50

标签: ruby-on-rails ruby delayed-job

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

伪代码,用于演示我希望能够做到的事情:

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

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

2 个答案:

答案 0 :(得分:1)

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

潜在解决方案

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

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

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

您还可以使用callback hooks。如果已定义,则延迟作业将通过error方法回调到您的有效内容对象。因此,您可以使用error方法通知您超出给定尝试次数的实际异常。要做到这一点......

在回调中,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

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

答案 1 :(得分:1)

为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发布他的答案之前开始写这篇文章。无论如何我都会发布它,因为它提供了一些关于如何处理异常和重新排队逻辑的更多细节。