Holds validated artifacts in ETS so serving them never touches disk.
Documentation JSON is read constantly and written rarely. Reading and decoding a file per request wastes work on every one of them, so the cache loads the whole artifact directory once at startup and answers from memory afterwards.
Add it to the host's supervision tree:
children = [
{DocShell.Web.Cache, dir: "priv/doc_shell/public"}
]fetch/2 reads an immutable generation in ETS directly from the calling
process, so lookups never queue behind the GenServer. The process exists to
own the table and serialize reloads, not to serve reads.
Disposable by design
The cache is derived state. The JSON files are the source of truth, so
crashing, restarting, or reloading cannot lose anything durable — which is
why init/1 can afford to fail hard. A directory of artifacts that will not
load is a deployment error, and starting anyway with a half-populated table
would turn it into a scattering of 404s that look like missing documentation.
reload/1 re-reads the directory after a rebuild. It is all-or-nothing: the
manifest and every listed artifact must carry the same generation_id.
The replacement generation is filled before one ETS pointer is switched, so
readers see the complete old or complete new snapshot, never an empty or
mixed table. DocShell.Artifact writes each file atomically for the same
reason.
Multiple caches
The registered :name doubles as the ETS table name, so several caches can
coexist over different directories:
{DocShell.Web.Cache, name: :docs_internal, dir: "priv/doc_shell/private"}Pass that name to fetch/2, or to DocShell.Web.Plug as :cache.
This module does not require Plug and is useful on its own to any host that wants artifacts in memory.
Summary
Functions
Returns a specification to start this module under a supervisor.
Fetches a cached artifact by filename from the given cache table.
Fetches a cached artifact as its complete stored envelope.
Re-reads the artifact directory, replacing the cache contents.
Starts the cache and loads a directory of JSON artifacts.
Functions
Returns a specification to start this module under a supervisor.
See Supervisor.
Fetches a cached artifact by filename from the given cache table.
Returns :error when the artifact is absent or the cache has not been started
(missing ETS table), so callers never crash on an unstarted cache.
Fetches a cached artifact as its complete stored envelope.
Serving needs this rather than fetch/2: the response has to carry the
generated_at of the build that produced the artifact, and rebuilding an
envelope around a bare payload would stamp it with the time of the request.
@spec reload(GenServer.server()) :: :ok | {:error, term()}
Re-reads the artifact directory, replacing the cache contents.
Returns {:error, {path, reason}} and leaves the previous contents in place
if any file fails to read or validate.
@spec start_link(keyword()) :: GenServer.on_start()
Starts the cache and loads a directory of JSON artifacts.
The registered :name (default DocShell.Web.Cache) is also used as the
ETS table name, so multiple independently-named caches can coexist.