Ruby on rails 3 延迟作业:如何强制处理失败的作业
我正在维护一个rails应用程序,在这个应用程序上运行用于发送电子邮件的delayed_job gem 我刚刚注意到,由于应用程序中的一个bug,我所有延迟的工作在过去几天都失败了。现在这个错误已经修复,我想尽快处理这些作业,但是它们已经有太多失败的尝试了,工作人员从数据库中拖出这些作业的时间非常延迟 我尝试更新delayed_jobs表,将尝试次数设置为较小的数字,并将run_at属性设置为当前时间,但仍然没有帮助Ruby on rails 3 延迟作业:如何强制处理失败的作业,ruby-on-rails-3,delayed-job,Ruby On Rails 3,Delayed Job,我正在维护一个rails应用程序,在这个应用程序上运行用于发送电子邮件的delayed_job gem 我刚刚注意到,由于应用程序中的一个bug,我所有延迟的工作在过去几天都失败了。现在这个错误已经修复,我想尽快处理这些作业,但是它们已经有太多失败的尝试了,工作人员从数据库中拖出这些作业的时间非常延迟 我尝试更新delayed_jobs表,将尝试次数设置为较小的数字,并将run_at属性设置为当前时间,但仍然没有帮助 您能告诉我如何强制工作人员执行这些命令吗?您可以手动启动,然后再试一次 Del
您能告诉我如何强制工作人员执行这些命令吗?您可以手动启动,然后再试一次
Delayed::Job.all.each { |j| j.invoke_job }
或
现在这个bug已经修复了,我想尽快处理这些作业,但是它们已经修复了
已经有太多失败的尝试,而工人将其从
数据库延迟了很长时间
这意味着,由于未从表中删除作业,因此仍有一些尝试等待延迟的作业。延迟作业的默认行为是在查找可用作业时从队列中读取5个作业。一种没有太多代码更改的方法是在延迟配置中设置一个从队列中拾取更多作业并执行。您可以通过设置Delayed::Worker.read\u 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天后到达。好的,所以我终于得到了它 诀窍是将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)>
现有的答案中没有一个是完全正确的,所以我在这里添加了这个 神奇之处在于让延迟的作业确信这些作业确实没有失败,因此通过rails 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”或“attempts”字段都可以阻止作业运行 谢谢你的建议。我已经经历过了,但这并不能解决我的问题-我的目标是在下一次计划执行之前强制执行。这听起来很合理,我现在就试试:)所以,我尝试了两种方法,但作业仍然没有处理。我是在rails控制台上做的,你知道我做错了什么吗?很难说这个答案实际上暗示了什么解决方案。对我来说,我只是在一个循环中更新以下内容,这将导致失败的作业在成功后被重新处理和删除:
Delayed::Job.where(“failed_at不是null”)。每个do | dj | dj.run_at=Time.now;dj.last_error=nil;dj.failed_at=nil;dj,救命!结束
我同意@steakchaser,这个答案没有包含足够的解决方案信息。但那是很久以前的事了,我对当时的情况记得不太清楚。我已经检查过了,将不给这个问题一个可接受的答案。
-> 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