Skip to content

Instantly share code, notes, and snippets.

@jeregrine
Created May 12, 2015 19:37
Show Gist options
  • Save jeregrine/87546cb18fc157f8a0a5 to your computer and use it in GitHub Desktop.
Save jeregrine/87546cb18fc157f8a0a5 to your computer and use it in GitHub Desktop.
Setting up Redo and Poolboy for redis connections in Elixir

Then add

worker(Redis, []),

to your supervision tree

defmodule Redis do
use Supervisor
def start_link() do
supervisor_name = Module.concat(__MODULE__, Supervisor)
Supervisor.start_link(__MODULE__, [], name: supervisor_name)
end
@doc false
def init([]) do
connection_string = System.get_env("REDIS_URL") || "redis://127.0.0.1:6379"
pool_size = (System.get_env("REDIS_POOL_SIZE") || "10") |> String.to_integer
max_overflow = (System.get_env("max_overflow") || "0") |> String.to_integer
%URI{host: host, port: port, userinfo: userinfo} = URI.parse(connection_string)
opts = Keyword.merge([], host: String.to_char_list(host))
opts = Keyword.merge([], port: port)
if userinfo do
[user, pass] = String.split(userinfo, ":")
opts = Keyword.put(opts, :pass, String.to_char_list(pass))
opts = Keyword.put(opts, :user, String.to_char_list(user))
end
pool_name = Module.concat(__MODULE__, Pool)
pool_opts = [
name: {:local, pool_name},
worker_module: Redis.Worker,
size: pool_size,
max_overflow: max_overflow
]
children = [
:poolboy.child_spec(pool_name, pool_opts, [opts]),
]
supervise children, strategy: :one_for_one
end
def cmd(command_list) do
:poolboy.transaction Redis.Pool, fn worker_pid ->
case GenServer.call(worker_pid, :conn) do
{:ok, conn_pid} ->
case :redo.cmd(conn_pid, command_list) do
{:error, reason} -> {:error, reason}
result -> result
end
{:error, reason} -> {:error, reason}
end
end
end
end
defmodule Redis.Worker do
use GenServer
def start_link(opts) do
GenServer.start_link(__MODULE__, opts)
end
def init([opts]) do
Process.flag(:trap_exit, true)
{:ok, {:disconnected, opts}}
end
def handle_call(:conn, _, {:disconnected, opts}) do
case :redo.start_link(:undefined, opts) do
{:ok, pid} -> {:reply, {:ok, pid}, {pid, opts}}
{:error, err} -> {:reply, {:error, err}, {:disconnected, opts}}
end
end
def handle_call(:conn, _, {pid, opts}) do
{:reply, {:ok, pid}, {pid, opts}}
end
def handle_info({:EXIT, pid, _}, {pid, opts}) do
{:noreply, {:disconnected, opts}}
end
def handle_info(_, state) do
{:noreply, state}
end
def terminate(_reason, {:disconnected, _}), do: :ok
def terminate(_reason, {pid, _}), do: :redo.shutdown(pid)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment