Current section
Files
Jump to
Current section
Files
lib/elasticachex.ex
defmodule Elasticachex do
@moduledoc """
An implementation of the Node Auto Discovery for Memcached in the
ElastiCache service of AWS.
It simply returns the nodes of the cache cluster.
"""
@socket Application.get_env(:elasticachex, :socket_module,
Elasticachex.Socket)
@timeout Application.get_env(:elasticachex, :timeout, 5000)
@doc """
The function to get the cluster info.
Returns `{:ok, [hosts_list], config_version}` or
`{:error, reason}`
"""
def get_cluster_info(host, port \\ 11_211) do
with {:ok, socket} <- @socket.connect(host, port, @timeout),
do: do_get_cluster_info(socket)
end
defp do_get_cluster_info(socket) do
with {:ok, command} <- get_command(socket),
{:ok, data} <- @socket.send_and_recv(socket, command, @timeout),
:ok <- @socket.close(socket) do
digest_cluster_data(data)
else
_ -> @socket.close(socket)
end
end
defp digest_cluster_data(data) do
values = String.split(data, "\n")
case length(values) do
6 ->
config_version = Enum.at(values, 1)
hosts_string = Enum.at(values, 2)
{:ok, get_hosts_list(hosts_string), config_version}
_ ->
{:error, "Not recognized response from endpoint"}
end
end
defp get_hosts_list(hosts_string) do
hosts_string
|> String.split(" ")
|> Enum.reduce([], fn(x, acc) ->
parts = String.split(x, "|")
["#{Enum.at(parts, 1)}:#{Enum.at(parts, 2)}" | acc]
end)
end
# The command to execute is different depending on versions
defp get_command(socket) do
case get_version(socket) do
{:ok, version} ->
case Version.compare(version, "1.4.14") do
:lt -> {:ok, "get AmazonElastiCache:cluster\n"}
_ -> {:ok, "config get cluster\n"}
end
{:error, reason} -> {:error, reason}
end
end
# Gets version number
defp get_version(socket) do
case @socket.send_and_recv(socket, "version\n", @timeout) do
{:ok, data} ->
<<"VERSION ", version :: binary >> = data
{:ok, String.trim(version)}
{:error, reason} -> {:error, reason}
end
end
end