defmodule Cache.SandboxRegistry do
@moduledoc """
This module is used to start the sandbox registry and register caches in test mode
More details soon...
"""
@sleep_for_sync 50
@registry :elixir_cache_sandbox
@keys :duplicate
@spec start_link :: {:error, any} | {:ok, pid}
def start_link do
Registry.start_link(keys: @keys, name: @registry)
end
def start(cache_or_caches) do
Cache.SandboxRegistry.register_caches(cache_or_caches)
if is_list(cache_or_caches) do
ExUnit.Callbacks.start_supervised!({Cache, cache_or_caches})
else
ExUnit.Callbacks.start_supervised!({Cache, [cache_or_caches]})
end
end
def register_caches(cache_module_or_modules, pid \\ self())
def register_caches(cache_modules, pid) when is_list(cache_modules) do
Enum.map(cache_modules, ®ister_caches(&1, pid))
end
def register_caches(cache_module, pid) do
key = unique_id(cache_module, pid)
res =
case SandboxRegistry.register(@registry, cache_module.cache_name(), key, @keys) do
:ok -> :ok
{:error, :registry_not_started} -> raise_not_started!()
end
Process.sleep(@sleep_for_sync)
res
end
def find!(cache_module, pid \\ self()) do
case SandboxRegistry.lookup(@registry, cache_module.cache_name()) do
{:ok, unique_id} ->
unique_id
{:error, :pid_not_registered} ->
raise """
No Cache registered for #{inspect(pid)}
======= Use: =======
#{format_example(cache_module)}
=== in your test ===
"""
{:error, :registry_not_started} ->
raise_not_started!()
end
end
defp unique_id(cache_name, pid), do: "#{cache_name}_#{inspect(pid)}"
defp format_example(cache_module) do
"""
setup do
Cache.SandboxRegistry.register_caches(#{inspect(cache_module)})
end
"""
end
defp raise_not_started! do
raise """
Registry not started for Cache.Sandbox.
Please add the line:
Cache.SandboxRegistry.start_link()
to test_helper.exs for the current app.
"""
end
end