2015-09-16 18 views
11

在導軌和ActionJob接口的通用模式是成立一個工作與perform()方法得到通過perform_nowperform_later差異deliver_later`

異步調用在特殊郵件程序的情況下,可以直接調用自ActionJobdeliver_nowdeliver_later都很好,ActionMailer集成。

rails documentation有以下評論 -

# If you want to send the email now use #deliver_now 
UserMailer.welcome(@user).deliver_now 

# If you want to send the email through Active Job use #deliver_later 
UserMailer.welcome(@user).deliver_later 

的措辭使得它看起來像deliver_now使用ActiveJob發送郵件。這是否正確,如果是這樣,deliver_nowdeliver_later之間的真正區別是什麼?一個不是異步的嗎?

同樣,也同樣差適用於perform_nowperform_later

謝謝!

回答

13

正如你在你的問題,deliver_now不使用ActiveJob

基本上,deliver_later是異步的。當您使用此方法時,電子郵件目前不會發送,而是被推送到作業隊列中。如果作業未運行,則不會發送電子郵件。無論工作狀態如何,deliver_now都會立即發送電子郵件。 Here你可以看到deliver方法的文檔。

根據你的第二個問題,perform_now將立即處理作業而不發送到隊列中。然而,perform_later會將作業添加到隊列中,並且只要作業的隊列空閒,就會執行該作業。 Here你可以看到perform方法的文檔。

+0

如果什麼瀏覽器連接被關閉?deliver_later還會執行嗎? – gates

+2

@gates'deliver_later'在服務器端進行管理,因此瀏覽器連接是否關閉並不重要。一旦作業被推入隊列,它將被髮送(除非你終止作業過程)。 –

+0

謝謝丹尼爾.. – gates

2

除了丹尼爾巴塔拉寫的東西之外,還有一個我觀察到的結果:deliver_later似乎執行懶惰評估,而deliver_now沒有。

我有沒有存儲在數據庫中的附加屬性reset_token ActiveRecord模型(這是來自邁克爾·哈特爾的railstutorial.org;模型在reset_digest列存儲令牌的哈希版本)。

執行deliver_now時,在郵件視圖內訪問@modelreset_token屬性會按預期產生重置令牌。但是,執行deliver_later時,@model.reset_token總是nil。看起來好像deliver_later使用數據庫數據更新模型,並且因爲reset_token是一個額外的屬性,它不會被數據庫支持,所以在那一點上它將是nil。 (代碼文檔太深,可以在源代碼中進行驗證。)

Michael在教程中使用了deliver_now。我不知道他這樣做是爲了避免懶惰的評估。但我花了一段時間才意識到,我只需將deliver_later更改爲deliver_now即可讓我的測試通過。

+0

由於'deliver_later'是異步的,它需要重新加載對象。就像任何異步作業一樣。因爲需要對工作進行新的更改(如果有的話)。 – Monika

+1

謝謝@bovender。我只是有同樣的問題。在我的模型中,有幾種計算總價格/總價格的方法,如果我按照以下方式運行郵件程序:Mailer.payment_email(model,calculate_price).deliver_later',price'總是'nil'。 'deliver_now'的使用有所幫助,但是它毀掉了異步傳遞的所有好處。爲了克服它,我用'calculate_price.to_f'替換了'calculate_price',它強制進行方法評估。在其他情況下,它可能是'to_i','to_s'等,這取決於方法返回的數據類型。 – ololobus