Current section
Files
Jump to
Current section
Files
lib/manifester.ex
defmodule Manifester do
@moduledoc """
A simple tool for getting digested asset paths out of the cache manifest.
See `README.md` to set up and `Manifester.get/1` for usage.
"""
use GenServer
require Logger
@name __MODULE__
@cache_manifest "static/cache_manifest.json"
#
# Client
#
def start_link(_args) do
GenServer.start_link(__MODULE__, :ok, name: @name)
end
@doc """
Performs a search for an asset, for example:
iex> Manifester.get("js/app.js")
"js/app-53ddc50a336555354d6b3d18b76d8af6.js"
"""
@spec get(String.t) :: String.t
def get(asset_path) do
GenServer.call(@name, {:get, asset_path})
end
#
# Server
#
@doc """
Initialises the process, builds cache immediately afterwards.
"""
def init(:ok) do
Logger.info("Manifester initialising")
Process.send(self(), :build_cache, [])
{:ok, []}
end
def handle_info(:build_cache, _cache) do
otp_app = Application.fetch_env!(:manifester, :otp_app)
priv_dir_path = to_string(:code.priv_dir(otp_app))
manifest_path = Path.join([priv_dir_path, @cache_manifest])
cache =
if File.exists?(manifest_path) do
# Cache manifest is only generated in prod builds.
manifest_path
|> File.read!()
|> Jason.decode!()
|> Map.get("latest")
else
%{}
end
{:noreply, cache}
end
def handle_call({:get, asset_path}, _from, cache) do
# There are no leading slashes in the cache_manifest.json
# file so we make sure we drop it if one is given.
asset_path =
if String.starts_with?(asset_path, "/") do
String.replace_leading(asset_path, "/", "")
else
asset_path
end
result = Map.get(cache, asset_path)
{:reply, result, cache}
end
end