2012-07-19 54 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」或企圖場可以從運行保住工作。