Current section

Files

Jump to
elixir_cache lib cache.ex
Raw

lib/cache.ex

defmodule Cache do
@moduledoc "#{File.read!("./README.md")}"
use Supervisor
@callback child_spec({
cache_name :: atom,
cache_opts :: Keyword.t()
}) :: Supervisor.child_spec() | :supervisor.child_spec()
@callback opts_definition() :: Keyword.t()
@callback put(cache_name :: atom, key :: atom | String.t(), ttl :: pos_integer, value :: any) ::
:ok | ErrorMessage.t()
@callback put(
cache_name :: atom,
key :: atom | String.t(),
ttl :: pos_integer,
value :: any,
Keyword.t()
) :: :ok | ErrorMessage.t()
@callback get(cache_name :: atom, key :: atom | String.t()) :: ErrorMessage.t_res(any)
@callback get(cache_name :: atom, key :: atom | String.t(), Keyword.t()) ::
ErrorMessage.t_res(any)
@callback delete(cache_name :: atom, key :: atom | String.t(), opts :: Keyword.t()) ::
:ok | ErrorMessage.t()
@callback delete(cache_name :: atom, key :: atom | String.t()) :: :ok | ErrorMessage.t()
defmacro __using__(opts) do
quote do
opts = unquote(opts)
@cache_opts opts
@cache_name opts[:name]
@cache_adapter if opts[:sandbox?], do: Cache.Sandbox, else: opts[:adapter]
if !opts[:adapter] do
raise "Must supply a cache adapter for #{__MODULE__}"
end
if !@cache_name do
raise "Must supply a cache name for #{__MODULE__}"
end
adapter_opts = if opts[:sandbox?], do: [], else: opts[:opts]
@adapter_opts NimbleOptions.validate!(adapter_opts, @cache_adapter.opts_definition())
@compression_level @adapter_opts[:compression_level]
if macro_exported?(unquote(opts[:adapter]), :__using__, 1) do
use unquote(opts[:adapter])
end
def cache_name, do: @cache_name
def cache_adapter, do: @cache_adapter
def child_spec(_) do
@cache_adapter.child_spec({@cache_name, @adapter_opts})
end
def put(key, ttl \\ nil, value) do
value = Cache.TermEncoder.encode(value, @compression_level)
key = maybe_sandbox_key(key)
@cache_adapter.put(@cache_name, key, ttl, value, @adapter_opts)
end
def get(key) do
key = maybe_sandbox_key(key)
with {:ok, value} when not is_nil(value) <-
@cache_adapter.get(@cache_name, key, @adapter_opts) do
{:ok, Cache.TermEncoder.decode(value)}
end
end
def delete(key) do
key = maybe_sandbox_key(key)
@cache_adapter.delete(@cache_name, key, @adapter_opts)
end
if @cache_opts[:sandbox?] do
defp maybe_sandbox_key(key) do
sandbox_id = Cache.SandboxRegistry.find!(__MODULE__)
"#{sandbox_id}:#{key}"
end
else
defp maybe_sandbox_key(key) do
key
end
end
end
end
def start_link(cache_children, opts \\ []) do
Supervisor.start_link(Cache, cache_children, opts)
end
def init(cache_children) do
Supervisor.init(cache_children, strategy: :one_for_one)
end
end