3
votes

This is a bit of an odd question. We are writing an elixir application that will test various pieces of infrastructure of different applications.

Esentially what I want to do but have not been able to do is simulate a redis connection error and be able to recover from that error. Since both Redix and Exredis seem to raise errors from within the new connection pid, I am unable to actually do anything.

Example of what we essentially need:

def is_redis_down() do
      {:ok, conn} = Redix.start_link("redis://wrong", name: :redix) 
          case Redix.command(conn, ["ping"]) do
              {:ok, response} ->
                  Redix.stop(conn)
                  response !== "PONG"
              {:error, _ } ->       
                  GenServer.stop(conn, :normal)
                  true
          end
    end

The problem is, if you keep the connection string as something wrong, start_link returns a Pid, but the case statement is never run. Its like the start_link crashes the parent pid. Any ideas on how to recover? I just want a true if it connects and sends a ping, or a false if it fails to connect.

Ive tried nesting inside a Task and a separate pid.

1

1 Answers

3
votes

Redix has a sync_connect option. If you set that to true, the function will return after the link is established, or crash if there was an error. You can use Process.flag(:trap_exit, true) to trap exit messages to prevent your parent process from crashing. After that, you just need to check for {:ok, conn} and {:error, error}:

defmodule A do
  def is_redis_down() do
    Process.flag(:trap_exit, true)
    case Redix.start_link("redis://wrong", sync_connect: true) do
      {:ok, _} -> true
      {:error, _} -> false
    end
  end
end

IO.inspect A.is_redis_down()

If you don't want to change the trap_exit of parent process, you can spawn a not-linked Task and do this computation in that.