2012-07-19 51 views
3

我正在维护一个rails应用程序,在该应用程序上运行用于发送电子邮件的delayed_job gem。delayed_job:如何强制处理失败的作业

我刚刚注意到,由于应用程序中存在一个错误,我所有延迟的工作都失败了。现在这个bug已经修复了,我想尽快处理这些工作,但是他们已经有太多的失败尝试,并且工作人员将这些工作从数据库中扯下来,并且延迟很大。

我试过更新delayed_jobs表,并将尝试的次数设置为较小的数字,将run_at属性设置为当前时间,但仍然没有帮助。

你能告诉我如何强制工人执行它们吗?

回答

10

您可以手动启动它,尝试

Delayed::Job.all.each { |j| j.invoke_job } 

Delayed::Job.all.each { |j| j.payload_object.perform } 
+0

这听起来很合理,我现在试试:) – 2012-07-19 10:11:53

+0

所以,我试过这两种方法,但仍然没有处理这些作业。我做了从轨道控制台,任何想法我做错了什么? – 2012-07-19 10:47:22

1

现在的错误是固定的,我想尽快处理工作,但他们 有已经太多了失败的尝试,并且该工作人员将其从数据库中扯下来,造成巨大的延迟。

这意味着,并且由于作业不会从表格中删除,因此还有一些延迟作业的剩余尝试。延迟作业的默认行为是在查找可用作业时从队列中读取5个作业。没有太多代码更改的一种方法是在延迟配置中设置一个设置,该设置将从队列中获取更多作业并执行。您可以通过设置Delayed::Worker.read_ahead进行配置。

# config/initializers/delayed_job_config.rb 
Delayed::Worker.destroy_failed_jobs = false 
Delayed::Worker.read_ahead = 10 

Delayed::Worker.destroy_failed_jobs避免最大的尝试,这也是一个配置项后的就业删除。

在数据库中每5秒延迟作业检查可用作业,它会在5 + N ** 4秒后尝试特定作业。所以说,如果某项工作已经失败了24次,那么它将在331781秒后到达,即如果我没有错,大致在3天后到达。

+0

感谢您的建议。我已经完成了这个工作,但这并没有解决我的问题 - 我的目标是在下一次计划执行之前强制执行。 – 2012-07-19 10:11:09

3

好吧,最后我明白了!

诀窍在于将run_at属性更新为当前时间,但是该应用程序的当前时间 - 位于数据库后面3小时。

当我将它设置为now() - 间隔'3小时'时,所有作业都被处理。

编辑:

@rodzyn,我想你的建议,但还是没能得到它的工作:

[20] pry(main)> Delayed::Job.all.size 
    Delayed::Backend::ActiveRecord::Job Load (0.6ms) SELECT "delayed_jobs".* FROM "delayed_jobs" 
=> 1 
[21] pry(main)> Delayed::Job.first.invoke_job 
    Delayed::Backend::ActiveRecord::Job Load (0.5ms) SELECT "delayed_jobs".* FROM "delayed_jobs" LIMIT 1 
    Order Load (0.4ms) SELECT "orders".* FROM "orders" WHERE "orders"."id" = $1 LIMIT 1 [["id", "328"]] 
    User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1 
=> nil 
[22] pry(main)> Delayed::Job.all.size 
    Delayed::Backend::ActiveRecord::Job Load (0.6ms) SELECT "delayed_jobs".* FROM "delayed_jobs" 
=> 1 
[23] pry(main)> 
+4

很难说这个答案实际上是什么解决方案。对我来说,我只是在一个循环中更新以下内容,这将导致失败的作业在成功后被重新处理和删除:'Delayed :: Job.where(“failed_at is not null”)。each do | dj | dj.run_at = Time.now; dj.last_error = nil; dj.failed_at = nil; dj.save!结束' – steakchaser 2014-05-13 18:42:04

+0

我同意@steakchaser,这个答案不包含关于解决方案的足够信息。尽管这是很久以前的事情,我不太清楚这种情况。我没有选中它,并且会在没有被接受的答案的情况下留下问题。 – 2014-05-20 09:22:14

2

现有的答案都不具有这种完全正确的,所以我添加此这里。

神奇的是说服延迟工作,这些工作真不是失败,所以通过轨道DB控制台:

-> rails db 
development# update delayed_jobs set run_at = now() - interval '3 hours', attempts = 0, failed_at = null; 
UPDATE 30 
development# \q 

-> rake jobs:workoff # a good one to use, because it will return immediately if no jobs are found 

无论是“failed_at”或企图场可以从运行保住工作。