intercaetera

intercaetera

Error handling with "with"

Sort of a newbie code review question, but I’m curious if there’s a way to work around this. I’m still trying to wrap my head around good practices for error tuples. The precise code is in a Phoenix app but it could well exist outside of it. I have three functions in three modules:

# TaskRegistry
  def get_status(id) do
    with [{id, status}] <- :ets.lookup(:task_registry, id)
    do
      {:ok, {id, status}}
    else
      [] -> {:error, :file_not_found}
      _ -> {:error, :unknown}
    end
  end

  # TaskServer
  def handle_call({:status, id}, _, state) do
    with {:ok, {_, status}} <- TaskRegistry.get_status(id)
    do
      {:reply, {:ok, status}, state}
    else
      error -> {:reply, error, state}
    end
  end

  # TaskController
  def status(%Plug.Conn{path_params: %{"id" => id}} = conn, _params) do
    with {:ok, status} <- TaskServer.status(id)
    do
      json(conn, %{status: status})
    else
      {:error, :file_not_found} -> conn |> put_status(404) |> json(%{status: "not found"})
    end
  end

This doesn’t really seem right to me, that each of these has a with clause. But without it on each failed request the TaskServer crashes (and Phoenix returns HTTP 500, which is undesirable but not really relevant to the question). It doesn’t seem right that the GenServer should crash just because someone put in something wrong. I’m not sure how to refactor this well, though.

Most Liked

stefanchrobot

stefanchrobot

All these functions would be much better off with case instead of with. Avoid else in with is a pretty good advice.

al2o3cr

al2o3cr

It’s hard to say exactly what causes this crash without the code, but I’d guess it’s a MatchError when using code like the above but without with, turning <- to =

For an expression with one statement in the “happy path” of a with, case will be more readable:

  def get_status(id) do
    case :ets.lookup(:task_registry, id) do
      [{id, status}] -> {:ok, {id, status}}
      [] -> {:error, :file_not_found}
      _ -> {:error, :unknown}
    end
  end

Where Next?

Popular in Questions Top

chokchit
** (DBConnection.ConnectionError) connection not available and request was dropped from queue after 2733ms. You can configure how long re...
New
Darmani72
If I have a post route which an argument: post /my_post_route/:my_param1, MyController.my_post_handler How would get the post params ...
New
albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
tduccuong
Hi, is there any work on GUI with Elixir, that is similar to Electron/Javascript? My idea is to bundle Phoenix and BEAM into a single se...
New
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New
PeterCarter
There are pre-rolled solutions for other frameworks that do work. However, Phoenix does not seem to have these. Have people had good expe...
New
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New

Other popular topics Top

sen
Hi All, I set a environment variables in dev.exs , like below code. when i start server, how can i set the ${enable} value? thanks. d...
New
AstonJ
Posting this to see if we can make things easier for people to get into Neovim. If you use Neovim and have a favourite distro please let ...
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New
Nvim
Anybody knows a comprehensive comparison of Django and Phoenix, thanks for the help. Where are they similar? Where do they differ the m...
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New
AstonJ
We’ve put together this wiki for Phoenix LiveView - please feel free to add any info you feel is worth including. What is Phoenix LiveV...
New
JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1144 54120 245
New

We're in Beta

About us Mission Statement