Packages

Elixir client for the Routemaster event bus server. Supports publishing events, subscribing to topics, receiving and processing events. Also incluses a HTTP client integrated with a builtin cache service.

Current section

Files

Jump to
routemaster_client lib routemaster cache.ex
Raw

lib/routemaster/cache.ex

defmodule Routemaster.Cache do
@moduledoc """
A persistent cache that survives application restarts,
backed by Redis.
"""
alias Routemaster.Config
import Routemaster.Redis, only: [serialize: 1, deserialize: 1]
@type fallback :: (() -> any)
@redis Routemaster.Redis.Cache
@doc """
Reads a key-value and returns an Elixr term, in a tuple.
iex> Routemaster.Cache.read(:apple)
{:miss, nil}
iex> Routemaster.Cache.write(:apple, %{is: "a", good: "fruit"})
{:ok, %{is: "a", good: "fruit"}}
iex> Routemaster.Cache.read(:apple)
{:ok, %{is: "a", good: "fruit"}}
"""
@spec read(atom | binary) :: {:ok, any} | {:miss, nil} | {:error, any}
def read(key) do
case @redis.get(key) do
{:ok, nil} ->
{:miss, nil}
{:ok, data} ->
{:ok, deserialize(data)}
{:error, _} = error ->
error
end
end
@doc """
Writes a key-value and returns the written value, in a tuple.
iex> Routemaster.Cache.write(:pear, [1, 2, 3])
{:ok, [1, 2, 3]}
iex> Routemaster.Cache.read(:pear)
{:ok, [1, 2, 3]}
"""
@spec write(atom | binary, any) :: {:ok, any} | {:error, any}
def write(key, term) do
case @redis.setex(key, Config.cache_ttl, serialize(term)) do
{:ok, "OK"} ->
{:ok, term}
{:error, _} = error ->
error
end
end
@doc """
Tries to read `key` from the cache, and returns the stored value
if anything is found. If no vlaue is found in the cache, it
executes the `fallback` function, caches the result, and returns
the value in a tuple.
iex> Routemaster.Cache.read(:peach)
{:miss, nil}
iex> Routemaster.Cache.fetch(:peach, fn() -> "apricot" end)
{:ok, "apricot"}
iex> Routemaster.Cache.fetch(:peach, fn() -> "coconut" end)
{:ok, "apricot"}
iex> Routemaster.Cache.read(:peach)
{:ok, "apricot"}
"""
@spec fetch(atom | binary, fallback) :: {:ok, any} | {:error, any}
def fetch(key, fallback) do
case read(key) do
{:miss, _} ->
write(key, fallback.())
{:ok, _} = value ->
value
{:error, _} = error ->
error
end
end
@doc """
It clears a key-value from the cache
iex> Routemaster.Cache.write(:mango, "so good")
{:ok, "so good"}
iex> Routemaster.Cache.clear(:mango)
:ok
iex> Routemaster.Cache.read(:mango)
{:miss, nil}
"""
@spec clear(atom | binary) :: :ok | :error
def clear(key) do
case @redis.del(key) do
{:ok, _n} -> :ok # n is 0 or 1
_ -> :error
end
end
end