Current section
Files
Jump to
Current section
Files
lib/memcachir.ex
defmodule Memcachir do
@moduledoc """
Module with a friendly API for memcached servers.
It provides connection pooling, and cluster support.
## Example
{:ok} = Memcachir.set("hello", "world")
{:ok, "world"} = Memcachir.get("hello")
"""
use Application
alias Memcachir.Util
@doc """
Starts application.
"""
def start(_type, _args) do
servers = get_servers()
# Build the hashring
{:ok, _pid} = HashRing.Managed.new(:memcachir_ring)
Enum.each(servers, fn({host, port}) ->
:ok = HashRing.Managed.add_node(
:memcachir_ring, Util.host_to_atom(host, port))
end)
options =
Application.get_all_env(:memcachir)
|> Keyword.put(:servers, servers)
pool_options = Application.get_env(:memcachir, :pool, [])
Memcachir.Supervisor.start_link(options, pool_options)
end
@doc """
Gets the value associated with the key. Returns `{:error, "Key not found"}`
if the given key doesn't exist.
"""
def get(key, opts \\ []) do
node = key_to_node(key)
execute(&Memcache.get/3, node, [key, opts])
end
@doc """
Sets the key to value.
"""
def set(key, value, opts \\ []) do
node = key_to_node(key)
execute(&Memcache.set/4, node, [key, value, opts])
end
@doc """
Removes the item with the specified key. Returns `{:ok, :deleted}`
"""
def delete(key) do
node = key_to_node(key)
execute(&Memcache.delete/2, node, [key])
end
@doc """
Removes all the items from the server. Returns `{:ok}`.
"""
def flush(opts \\ []) do
nodes = servers_atoms()
execute(&Memcache.flush/2, nodes, [opts])
end
def execute(fun, nodes, args \\ [])
def execute(fun, [node | nodes], args) do
if length(nodes) > 0 do
execute(fun, nodes, args)
end
execute(fun, node, args)
end
def execute(fun, node, args) do
:poolboy.transaction(node, fn(worker) ->
apply(fun, [worker | args])
end)
end
defp key_to_node(key) do
HashRing.Managed.key_to_node(:memcachir_ring, key)
end
# Returns a list like [:localhost_11211, :localhost_11212]
defp servers_atoms() do
Enum.map(get_servers(), fn({host, port}) ->
Util.host_to_atom(host, port)
end)
end
# Returns a list like [{host1, port1}, {host2, port2}, ...]
# from the configured hosts parameter or reading it from elasticache
defp get_servers() do
case Application.get_env(:memcachir, :elasticache) do
nil ->
Util.read_config_hosts(Application.get_env(:memcachir, :hosts))
elasticache ->
Util.read_config_elasticache(elasticache)
end
end
end