Spaces:
Sleeping
Sleeping
defmodule Srh.Redis.ClientWorker do | |
use GenServer | |
def start_link(connection_info) do | |
GenServer.start_link(__MODULE__, connection_info, []) | |
end | |
def init(connection_info) do | |
Process.send(self(), :create_connection, []) | |
{ | |
:ok, | |
%{ | |
connection_info: connection_info, | |
redix_pid: nil | |
} | |
} | |
end | |
def redis_command(worker, command_array) do | |
GenServer.call(worker, {:redis_command, command_array}) | |
end | |
def destroy_redis(worker) do | |
GenServer.cast(worker, {:destroy_redis}) | |
end | |
def handle_call({:redis_command, command_array}, _from, %{redix_pid: redix_pid} = state) | |
when is_pid(redix_pid) do | |
case Redix.command(redix_pid, command_array) do | |
{:ok, res} -> | |
{:reply, {:ok, res}, state} | |
# Both connection errors and Redis command errors will be handled here | |
{:error, res} -> | |
{:reply, {:error, res}, state} | |
end | |
end | |
def handle_call(_msg, _from, state) do | |
{:reply, :ok, state} | |
end | |
def handle_cast({:destroy_redis}, %{redix_pid: redix_pid} = state) when is_pid(redix_pid) do | |
# Destroy the redis instance & ensure cleanup | |
Redix.stop(redix_pid) | |
Process.exit(redix_pid, :normal) | |
{:stop, :normal, %{state | redix_pid: nil}} | |
end | |
def handle_cast(_msg, state) do | |
{:noreply, state} | |
end | |
def handle_info( | |
:create_connection, | |
%{ | |
connection_info: %{ | |
"connection_string" => connection_string | |
} | |
} = state | |
) | |
when is_binary(connection_string) do | |
enable_ssl = String.starts_with?(connection_string, "rediss://") | |
socket_opts = | |
case enable_ssl do | |
true -> | |
[ | |
customize_hostname_check: [ | |
match_fun: :public_key.pkix_verify_hostname_match_fun(:https) | |
] | |
] | |
false -> | |
[] | |
end | |
# NOTE: Redix only seems to open the connection when the first command is sent | |
# This means that this will return :ok even if the connection string may not actually be connectable | |
{:ok, pid} = | |
Redix.start_link(connection_string, | |
ssl: enable_ssl, | |
socket_opts: socket_opts | |
) | |
{:noreply, %{state | redix_pid: pid}} | |
end | |
def handle_info(_msg, state) do | |
{:noreply, state} | |
end | |
end | |