Files
phosphoricons/lib/heroicons/cache.ex

54 lines
1.2 KiB
Elixir
Raw Normal View History

2022-09-02 13:49:03 -04:00
defmodule Heroicons.Cache do
@moduledoc """
An ETS-backed cache for icons. We cache both pre-compiled Phoenix Components and icon bodies as strings.
Uses the icon's path on disk as a key.
"""
2022-09-02 07:20:50 -04:00
use GenServer
@name __MODULE__
2022-09-02 13:49:03 -04:00
@doc false
2022-09-02 07:20:50 -04:00
def start_link(_), do: GenServer.start_link(__MODULE__, [], name: @name)
2022-09-02 21:01:48 -04:00
@doc "Fetch a icon's body and fingerprint from the cache or disk, given a `path`"
def fetch_icon(path) do
2022-09-02 07:20:50 -04:00
case :ets.lookup(@name, path) do
2022-09-02 21:01:48 -04:00
[{^path, icon_body, fingerprint}] ->
{icon_body, fingerprint}
2022-09-02 07:20:50 -04:00
[] ->
2022-09-02 21:01:48 -04:00
GenServer.call(@name, {:cache_icon, path})
2022-09-02 07:20:50 -04:00
end
end
2022-09-02 13:49:03 -04:00
@impl true
2022-09-02 07:20:50 -04:00
def init(_) do
:ets.new(@name, [:set, :protected, :named_table])
{:ok, []}
end
2022-09-02 13:49:03 -04:00
@impl true
2022-09-02 21:01:48 -04:00
def handle_call({:cache_icon, path}, _ref, state) do
{icon_body, fingerprint} = read_icon(path)
2022-09-02 07:20:50 -04:00
2022-09-02 21:01:48 -04:00
:ets.insert_new(@name, {path, icon_body, fingerprint})
2022-09-02 07:20:50 -04:00
2022-09-02 21:01:48 -04:00
{:reply, {icon_body, fingerprint}, state}
2022-09-02 07:20:50 -04:00
end
2022-09-02 21:01:48 -04:00
defp read_icon(path) do
2022-09-02 18:57:26 -04:00
icon =
Path.join(:code.priv_dir(:heroicons), path)
|> File.read!()
2022-09-02 21:01:48 -04:00
<<"<svg", icon_body::binary>> = icon
<<fingerprint::8*16>> = :erlang.md5(icon)
2022-09-02 21:01:48 -04:00
{icon_body, fingerprint}
end
end