genserver implementation to open redis state

112 Views Asked by At

I want to open a Redis connection and I have written a code something like this for persistent connection within the system. The way I'm doing this I'm calling a handle_info function which uses the Redix client. I have defined the dependency for redix

def start_link(opts \\ [name: __MODULE__]) do
    GenServer.start_link(__MODULE__, nil, Keyword.merge(opts, name: __MODULE__))
  end

  @impl true
  def init(_) do
    send(self(), :connect)
    {:ok, nil}
  end

  @impl true
  def handle_info(:connect, _conn) do
    host = "redis://localhost:6379/3"

    case Redix.start_link(host) do
      {:ok, conn} ->
        IO.inspect(conn)
        Process.monitor(conn.pid)
        {:noreply, conn}

      {:error, _} ->
       
        Process.send_after(self(), :connect, @reconnect_interval)
        {:noreply, nil}
    end
  end

I call with redix client to the server with handle info. When I use the PID to set a key in Redis something like this

Redix.command!(conn, ["SET", "queue"])

I get this error

    [error] GenServer Zuppler.Utils.Redis.Connection terminating
** (RuntimeError) attempted to cast GenServer Zuppler.Utils.Redis.Connection but no handle_cast/2 clause was provided
    (zuppler_utils 0.1.12) lib/gen_server.ex:824: Zuppler.Utils.Redis.Connection.handle_cast/2
    (stdlib 3.17.1) gen_server.erl:695: :gen_server.try_dispatch/4
    (stdlib 3.17.1) gen_server.erl:771: :gen_server.handle_msg/6
    (stdlib 3.17.1) proc_lib.erl:226: :proc_lib.init_p_do_apply/3
Last message: {:"$gen_cast", {:pipeline, [["llen", "list_name"]], {#PID<0.694.0>, #Reference<0.884395455.1828454401.122583>}, 5000}}
State: #PID<0.801.0>
** (EXIT from #PID<0.694.0>) shell process exited with reason: an exception was raised:
    ** (RuntimeError) attempted to cast GenServer Zuppler.Utils.Redis.Connection but no handle_cast/2 clause was provided
        (zuppler_utils 0.1.12) lib/gen_server.ex:824: Zuppler.Utils.Redis.Connection.handle_cast/2
        (stdlib 3.17.1) gen_server.erl:695: :gen_server.try_dispatch/4
        (stdlib 3.17.1) gen_server.erl:771: :gen_server.handle_msg/6
        (stdlib 3.17.1) proc_lib.erl:226: :proc_lib.init_p_do_apply/3
1

There are 1 best solutions below

3
Aleksei Matiushkin On

You already have IO.inspect(conn) which must have shown you conn is a pid. Right in the next line you try to call conn.pid which is treated as a function call, which maps to :erlang.apply(#PID<0.1075.0>, :pid, []) and obviously raises. The following would most likely do.

- Process.monitor(conn.pid)
+ Process.monitor(conn)

Sidenote: use GenServer.handle_continue/2 callback instead of sending the message to self which exists for exactly this kind of initialization.

Also, one usually starts Redix within the application supervision tree as described in the documentation.