Правильный способ создать фоновое задание в приложении elixir phoenix

  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 является синхронным, и запрос ожидает.

Я хотел сделать его асинхронным, поэтому вместо этого создал такой процесс

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

Запрос не ждет, пока почта не будет отправлена.

  • Хотя это работает, это правильный способ сделать?
  • Есть ли шансы, что эти процессы станут сиротами или просто умрут после немедленного выполнения?
  • Должны ли мы вместо этого создать Supervisor?
  • Должны ли мы вместо этого использовать библиотеку типа https://github.com/akira/exq? (Я чувствую, что даже если spawn_link выйдет из строя и зарегистрирует это в наших журналах phoenix, это подойдет)

person Vysakh Sreenivasan    schedule 30.11.2015    source источник


Ответы (2)


Запуск процесса с использованием spawn_link/1 приведет к двунаправленной ссылке, поэтому любой из порождающих процессов и вновь порожденных процессов, которые умирают первыми, убивает другой (если только он не перехватывает выходы, чего, вероятно, не должно быть). В одних случаях это здорово, а в других — не очень; например, если отправка этого электронного письма занимает много времени, запрос Phoenix может завершиться первым и может привести к уничтожению порожденного процесса.

Однако из-за связывания не должно быть никакого риска того, что процессы станут осиротевшими.

Лучший подход, безусловно, состоит в том, чтобы создать Supervisor (или использовать Task.Supervisor), и вы можете довольно легко свернуть свою собственную настройку фонового задания.

Однако, возможно, стоит взглянуть на что-то вроде exq, о котором вы упомянули, или, например, Toniq, в котором, возможно, уже есть все, что вам нужно. ; особенно такие вещи, как повторные попытки в случае сбоя и сохранение. Есть также несколько других интересных вариантов в списке Awesome Elixir, если вы хотите попробовать несколько разных альтернатив.

person Johan Wärlander    schedule 30.11.2015
comment
Кстати, для списка с параметрами фоновой очереди вы можете проверить elixir.libhunt.com/categories/862 -queue тоже. Я надеюсь, что это полезно. - person Stan Bright; 23.11.2016

Я считаю, что вы можете просто использовать spawn\3, и это сделает работу, но проблема здесь в том, что, как было упомянуто Йоханом, не будет никаких повторных попыток или интерфейса для отслеживания заданий и т. д., так что вам, вероятно, лучше отключить использование внешней библиотеки.

person NoDisplayName    schedule 01.12.2015