2015-11-30 27 views
10
def create(conn, %{"data" => %{"attributes" => user_params}}) do 

    changeset = User.changeset(%User{}, user_params) 

    case Repo.insert(changeset) do 
     {:ok, user} -> 
     UserMailer.send_welcome_email(user) 
     conn 
     |> put_status(:created) 
     |> render("show.json", model: user) 
     {:error, changeset} -> 
     conn 
     |> put_status(:unprocessable_entity) 
     |> render(MyApp.ChangesetView, "error.json", changeset: changeset) 
    end 
    end 

在此控制器操作中,UserMailer.send_welcome_email是同步的,並且請求等待。在elixir鳳凰應用程序中創建後臺作業的正確方法

我想讓它異步的,因此催生了一個過程像這樣反而

spawn_link(fn -> 
    UserMailer.send_welcome_email(user) 
end) 

請求不能等到郵件已發送。

  • 雖然它有效,但它是正確的做法嗎?
  • 這些過程成爲孤兒還是有機會立即執行後死亡?
  • 我們應該創建一個Supervisor嗎?
  • 我們應該使用像https://github.com/akira/exq這樣的庫嗎? (我覺得即使spawn_link失敗,並記錄在我們鳳凰的日誌,它會做)

回答

10

使用spawn_link/1會導致雙向鏈路啓動過程,故取其產卵進程和新生成的過程中發生這種情況首先死亡會殺死另一個(除非它陷入退出,這可能不應該)。在某些情況下這很好,在其他情況下也不是那麼好;例如,如果發送該電子郵件需要很長時間,Phoenix請求可能會首先完成,並有可能導致產生的進程失效。

但是,由於鏈接,應該不會有任何流程成爲孤兒的風險。

更好的方法是創建一個Supervisor(或使用Task.Supervisor),並且您可以輕鬆地滾動自己的後臺作業設置。

但是,可能需要查看您提到的exqToniq等其他可能具有您需要的所有內容;特別是在失敗的情況下重試的情況和持久性。在Awesome Elixir列表中還有其他一些有趣的選項,如果您想嘗試幾種不同的選擇。

+0

這是不是被接受的答案? – MartinElvar

+0

順便說一句,對於具有後臺隊列選項的列表,您還可以檢查https://elixir.libhunt.com/categories/862-queue。我希望這是有幫助的。 –

0

我相信你可以簡單地使用spawn\3,那樣做就可以完成這個任務,但問題在於,正如Johan提到的那樣,不會有任何重試或界面來追蹤工作等等,所以你'使用外部庫可能會更好。