2011-06-10 89 views
4

我有幾個場合,其中delayed_jobs將照顧提供4千電子郵件,如果這些電子郵件中的錯誤(例如,如果沒有電話),那麼它將重新啓動整個過程並嘗試發送另有4000封電子郵件。這會一直持續下去,直到我手動殺死整個過程。爲什麼delayed_jobs在出錯時循環?

在過去的幾年裏,我在不同的應用程序中發生過很多次,我很好奇它是否發生在其他人身上。他們做了什麼來克服它。

+0

你需要保持已發送的郵件的軌道。 – 2011-06-10 15:30:25

+0

你能否詳細說說Mohit Jain? – Trip 2011-06-10 15:32:41

回答

9

延遲作業通常只是一個由後臺進程中的worker執行的方法,而不是在應用程序的主線程(Rails應用程序的請求生命週期)期間執行。

如果你讀下documentation for delayed_job「血淋淋的細節」,它規定:

失敗時,作業在5秒內+ N ** 4,其中N是重試次數再調度。

默認的Worker.max_attempts是25.在此之後,作業或者被刪除(默認),或者保留在數據庫中並設置了「failed_at」。 默認爲25次嘗試,最後一次重試將在20天后,最後一次間隔將近100小時。

這聽起來像你正在描述的是delayed_jobs打算髮揮作用的方式 - 如果發送4000封電子郵件的作業在發送3000封電子郵件後失敗,它就會重新開始。您可能需要跟蹤已發送和尚未發送的內容,因此您的工作可以循環「未發送」的電子郵件(或適用於您的後臺進程的任何信息)。這樣,當您發送3000封電子郵件時,他們會被標記爲「已發送」,如果您的工作失敗,它將通過加載剩餘的1,000封「未發送」電子郵件並嘗試發送它們而重新開始。

如果你真的不想工作到自己重試失敗,你可以將下面的代碼添加到您的項目:

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

Brett,你會如何推薦,與delayed_job整合哪些電子郵件被髮送/未發送? – Trip 2011-06-10 15:34:24

+0

旅程:取決於您的應用程序的結構,您如何建模正在發送的電子郵件?也許你可以問關於你的結構細節的另一個問題?我的猜測是我會彙總通過電子郵件發送的數據,將它存儲在一個新表中,並且布爾屬性爲'is_sent',當它確認它發送了電子郵件時,您的作業設置爲true?也許在工作完成100%並且你確認他們被髮送後,你可以刪除他們(如果你擔心桌子變得太大)。只是一個猜測,很難說,不知道更多關於你的應用程序結構! – 2011-06-10 15:37:36

+0

嘿Brett,只是一個FYI,我想到了添加存儲在用戶模型中的數組的電子郵件的唯一ID。它在發送之前驗證數組中是否存在此id。非常感謝! – Trip 2011-06-10 15:44:33

4

我們有一個延遲就業這個確切原因的規則 - 每個作業必須是原子的。如果由於某種原因(例外,網絡錯誤等)導致作業失敗,那麼一定不會有副作用。

對於只修改數據庫的作業,解決方案很簡單 - 將作業包裝在事務中。

對於與外部服務交互(發送電子郵件,打擊API等)的作業,我們嘗試將每個任務分解爲單獨的作業。

在你的情況下,我們將創建4000個工作,1個發送每封電子郵件。如果他們中的一些人失敗了,他們會繼續重試,而不會一遍又一遍地向其他人發送電子郵件。

+0

我現在在'begin'和'rescue'語句中包裝我的作業,最終以'return true'語句結束。這樣,它永遠不會循環。 – Trip 2011-10-12 16:30:48

+0

這將停止發送給人們的工作,但如果它引發異常,那麼一些電子郵件將不會被髮送,而您永遠不會知道 – 2011-10-18 00:42:09