defmodule RedixClusteredClone do
@moduledoc """
Wrapper on top of RedixClustered to clone writes to a separate cluster
"""
use Supervisor
def start_link(opts) do
Supervisor.start_link(__MODULE__, opts, name: supervisor_name(opts))
end
def init(opts) do
{:ok, clone} = Keyword.fetch(opts, :clone)
clone_opts =
clone
|> Keyword.put(:name, cloned_cluster_name(opts))
|> Keyword.put_new(:prefix, Keyword.get(opts, :prefix))
children = [
%{id: :primary, start: {RedixClustered, :start_link, [opts]}},
%{id: :clone, start: {RedixClustered, :start_link, [clone_opts]}}
]
Supervisor.init(children, strategy: :one_for_one)
end
def supervisor_name(opts), do: :"#{RedixClustered.cluster_name(opts)}_super"
def cloned_cluster_name(o) when is_list(o), do: cloned_cluster_name(Keyword.get(o, :name))
def cloned_cluster_name(nil), do: :clone
def cloned_cluster_name(name), do: :"#{name}_clone"
# pass through direct calls
defdelegate command(cmd), to: RedixClustered
defdelegate command(name, cmd), to: RedixClustered
defdelegate pipeline(cmds), to: RedixClustered
defdelegate pipeline(name, cmds), to: RedixClustered
# pass through read commands
defdelegate get(key), to: RedixClustered
defdelegate get(name, key), to: RedixClustered
defdelegate get_ttl(key), to: RedixClustered
defdelegate get_ttl(name, key), to: RedixClustered
defdelegate ttl(key), to: RedixClustered
defdelegate ttl(name, key), to: RedixClustered
defdelegate pttl(key), to: RedixClustered
defdelegate pttl(name, key), to: RedixClustered
defdelegate hgetall(key), to: RedixClustered
defdelegate hgetall(name, key), to: RedixClustered
defdelegate scan(pattern), to: RedixClustered
defdelegate scan(name, pattern), to: RedixClustered
# duplicate write commands to clone cluster
def expire(key, ttl), do: expire(nil, key, ttl)
def expire(name, key, ttl) do
RedixClustered.expire(cloned_cluster_name(name), key, ttl)
RedixClustered.expire(name, key, ttl)
end
def pexpire(key, ttl), do: pexpire(nil, key, ttl)
def pexpire(name, key, ttl) do
RedixClustered.pexpire(cloned_cluster_name(name), key, ttl)
RedixClustered.pexpire(name, key, ttl)
end
def set(key, val), do: set(nil, key, val)
def set(name, key, val) do
RedixClustered.set(cloned_cluster_name(name), key, val)
RedixClustered.set(name, key, val)
end
def setex(key, ttl, val), do: setex(nil, key, ttl, val)
def setex(name, key, ttl, val) do
RedixClustered.setex(cloned_cluster_name(name), key, ttl, val)
RedixClustered.setex(name, key, ttl, val)
end
def psetex(key, ttl, val), do: psetex(nil, key, ttl, val)
def psetex(name, key, ttl, val) do
RedixClustered.psetex(cloned_cluster_name(name), key, ttl, val)
RedixClustered.psetex(name, key, ttl, val)
end
def setnx_expire_get(key, ttl, val), do: setnx_expire_get(nil, key, ttl, val)
def setnx_expire_get(name, key, ttl, val) do
RedixClustered.setnx_expire_get(cloned_cluster_name(name), key, ttl, val)
RedixClustered.setnx_expire_get(name, key, ttl, val)
end
def del(key), do: del(nil, key)
def del(name, key) do
RedixClustered.del(cloned_cluster_name(name), key)
RedixClustered.del(name, key)
end
def hincrby(key, flds) when is_map(flds), do: hincrby(nil, key, flds)
def hincrby(key, flds, ttl) when is_map(flds), do: hincrby(nil, key, flds, ttl)
def hincrby(key, "" <> fld, num), do: hincrby(nil, key, fld, num)
def hincrby(name, key, flds) do
RedixClustered.hincrby(cloned_cluster_name(name), key, flds)
RedixClustered.hincrby(name, key, flds)
end
def hincrby(name, key, flds, ttl) do
RedixClustered.hincrby(cloned_cluster_name(name), key, flds, ttl)
RedixClustered.hincrby(name, key, flds, ttl)
end
def nuke(pattern), do: nuke(nil, pattern)
def nuke(name, pattern) do
RedixClustered.nuke(cloned_cluster_name(name), pattern)
RedixClustered.nuke(name, pattern)
end
end