Just to be clear, I suggested still crashing the http requests, but do it in a supervised non-linked task (or stream if there are multiple requests), so that the calling process that keeps the state doesn’t get linked and crash with the failing http request, but we still get the nice error message from the exception with the stacktrace.
# adapted the demo snippet from the docs for Task.Supervisor
# etc ...
def handle_info({:http_get, url} %{tasks: tasks} = state) do
task =
Task.Supervisor.async_nolink(MyApp.TaskSupervisor, fn ->
HTTPoison.get!(url) # <-- still using the `!` version to crash when appropriate
end)
{:reply, :ok, %{state | tasks: Map.put(tasks, task.ref, %{task: task, url: url})}}
end
# The task completed successfully
def handle_info({ref, %HTTPoison.Response{body: _body}}, %{tasks: %{ref => %{url: url}} = tasks} = state) do
# do something with the http reply
Process.demonitor(ref, [:flush])
{:noreply, %{state | tasks: Map.delete(tasks, ref)}}
end
def handle_info({ref, _}, state) do
# "response" from a "stray" task? Not sure when this can happen
{:noreply, state}
end
# The task failed
def handle_info({:DOWN, ref, :process, _pid, _reason}, %{tasks: %{ref => %{url: url}} = tasks} = state) do
# Log and possibly restart the task... (we still have the url for the request)
{:noreply, %{state | tasks: Map.delete(tasks, ref)}}
end
def handle_info({:DOWN, _ref, :process, _pid, _reason}, state) do
# I sometimes get the DOWN message even though the process has been demonitored, probably some internal race condition
{:noreply, state}
end
# etc ...






















