Подтвердить что ты не робот

Правильный способ создания фоновой работы в приложении 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, это будет делать)
4b9b3361

Ответ 1

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

В связи с связыванием, однако, не должно быть риска для процессов, потерявших сирот.

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

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

Ответ 2

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