Search code examples
elixirelixir-mix

Failed to run init method on using GenServer


I am new to elixir and recently found that GenServer is a good way to manage client/server API. So I tried to create a GenServer module to manage database connection but failed. Below is my code:

defmodule RedisClient do
  use GenServer
  require Logger

  # Client
  def start(url) do
    GenServer.start(__MODULE__, {url})
  end

  def init({url}) do
    Logger.info("connect to url #{url}");
    case Redix.start_link(url) do
        {:ok, conn} -> {conn}
        {:error, err} -> {:error, err}
    end
  end

end

The module RedisClient is used to connect to a redis database in its init() method. But it returns below error:

iex(tbc@192-168-1-7)15> RedisClient.start("redis://localhost")
{:error, {:bad_return_value, {#PID<0.6623.0>}}}
iex(tbc@192-168-1-7)16> 
17:58:20.592 [info]  connect to url redis://localhost

nil

I don't understand why it returns an error and why it prints nil at the end. It works fine if I call Redis directly as below:

iex(tbc@192-168-1-7)17> Redix.start_link("redis://localhost")
{:ok, #PID<0.7443.0>}

It seems that the API call on Redix has no problem, so what wrong with my GenServer implementation?


Solution

  • You need to return {:ok, state} from init/1 on success:

    {:ok, conn} -> {:ok, conn}
    

    or since you're returning exactly what Redix.start_link returns, you can simply return that:

    def init({url}) do
      Logger.info("connect to url #{url}");
      Redix.start_link(url)
    end