【问题标题】:Why does delayed_jobs loop when it errors?为什么delayed_jobs出错时会循环?
【发布时间】:2011-09-12 14:21:29
【问题描述】:

我有几次delayed_jobs 会处理发送4000 封电子邮件的情况,如果这些电子邮件中有错误(例如,如果有一个 nil 呼叫),那么它将重新启动整个过程并尝试发送还有 4000 封电子邮件。这将无限期地持续下去,直到我手动杀死 -9 整个过程。

在过去的几年里,我在不同的应用程序中发生过很多次,我很好奇其他人是否也发生过这种情况。他们做了什么来克服它。

【问题讨论】:

  • 您需要跟踪已发送的邮件..
  • 你能详细说明 Mohit Jain 吗?

标签: ruby-on-rails delayed-job


【解决方案1】:

延迟作业通常只是由工作人员在后台进程中执行的方法,而不是在应用程序的主线程期间(Rails 应用程序的请求生命周期)。

如果您阅读“血腥细节”下的documentation for delayed_job,它会指出:

如果失败,作业会在 5 秒 + N ** 4 后再次调度,其中 N 是重试次数。

默认的 Worker.max_attempts 是 25。在此之后,作业要么被删除(默认),要么留在数据库中并设置了“failed_at”。 默认为 25 次尝试,最后一次重试将在 20 天后,最后一次间隔几乎是 100 小时。

听起来您所描述的是延迟工作的预期运作方式 - 如果发送 4,000 封电子邮件的作业在发送 3,000 封电子邮件后失败,它就会重新开始。您可能需要跟踪已发送和未发送的内容,以便您的工作可以遍历“未发送”电子邮件(或任何适合您的后台进程的信息)。这样,当您发送 3,000 封电子邮件时,它们会被标记为“已发送”,如果您的工作失败,它将通过加载剩余的 1,000 封“未发送”电子邮件并尝试发送来重新开始。

如果您真的不希望作业在失败时重试,您可以将以下代码添加到您的项目中:

# config/initializers/delayed_job_config.rb
Delayed::Worker.max_attempts = 1

【讨论】:

  • Brett,你会如何推荐,与 delay_job 集成哪些电子邮件已发送/未发送?
  • Trip:取决于您的应用程序的结构,您如何对正在发送的电子邮件进行建模?也许你可以问另一个关于你的结构细节的问题?我的猜测是我会聚合通过电子邮件发送的数据,将其存储在具有布尔属性is_sent 的新表中,当确认它发送电子邮件时,您的工作设置为 true?也许在作业 100% 完成并且您确认它们已发送之后,您可以删除它们(如果您担心表格变得太大)。只是猜测,如果不了解您的应用程序结构,很难说!
  • 嘿,Brett,仅供参考,我想将生成的电子邮件的唯一 ID 添加到存储在 User 模型中的数组中。它在发送之前验证该 id 在数组中的存在。非常感谢!
  • 没问题,很高兴我能帮上忙!
【解决方案2】:

出于这个确切原因,我们有一个延迟作业的规则 - 每个作业都必须是原子的。如果作业由于某种原因(异常、网络错误等)失败,那么一定没有副作用。

对于只修改数据库的作业,解决方案很简单 - 将作业包装在事务中。

对于与外部服务交互的作业(发送电子邮件、访问 API 等),我们会尝试将每个任务分解为单独的作业。

在您的情况下,我们将创建 4000 个工作岗位,其中 1 个用于发送每封电子邮件。如果其中一些失败,那么他们将继续重试,而不会一遍又一遍地向其他人发送电子邮件。

【讨论】:

  • 我现在将我的工作包装在 beginrescue 语句中,最后以 return true 语句结束。这样,它就永远不会循环。
  • 这将阻止工作一遍又一遍地发送给人们,但如果它在中途抛出异常,那么一些电子邮件将不会发送,你永远不会知道
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-31
  • 1970-01-01
相关资源
最近更新 更多