On-disk cache for rendered OG PNGs.
Cache key = SHA-256 of (template_uuid, template_updated_at, canvas, binding_values). Two different posts with the same resolved values
share a single file; editing the template invalidates every dependent
cache entry automatically (the template's updated_at is part of the
key).
Files live under System.tmp_dir!()/phoenix_kit_og_cache/ — a writable,
ephemeral scratch dir (NOT priv/static, which is read-only in a release),
read back by PhoenixKitOG.Web.ImageController at /og-image/:key and
streamed as image/png. Filename pattern:
<16-hex hash>.pngThe full hash is 64 hex; we truncate to 16 (64 bits) which is collision-resistant for our scale (millions of templates × posts).
Eviction
Every template edit mints new keys (the updated_at is hashed in) and
orphans the old files, so the dir grows monotonically without a bound.
write/2 therefore calls maybe_prune/0 on a small fraction of writes
(cheap amortized): it deletes files older than @ttl_seconds and, if
the count still exceeds @max_files, the oldest beyond the cap. A
still-valid render just re-renders on its next miss — the cache is a
performance layer, never a source of truth. Tune via
config :phoenix_kit_og, cache_ttl_seconds: _, cache_max_files: _.
Summary
Functions
Clears every cached render — useful after upgrading the renderer.
Deletes cache files older than the TTL and, if still over the count cap,
the oldest beyond it. Safe to call from a cron or by hand; write/2
calls it probabilistically. Never raises — a prune failure must not
break a render.
Writes the PNG bytes to the cache file. Atomic: write to a tempfile in the same dir then rename, so a concurrent read never sees a partial file.
Functions
@spec clear() :: :ok
Clears every cached render — useful after upgrading the renderer.
Returns {cache_key, absolute_path}. The path may or may not exist —
call exists?/1 or read/1 to check.
@spec prune() :: :ok
Deletes cache files older than the TTL and, if still over the count cap,
the oldest beyond it. Safe to call from a cron or by hand; write/2
calls it probabilistically. Never raises — a prune failure must not
break a render.
Writes the PNG bytes to the cache file. Atomic: write to a tempfile in the same dir then rename, so a concurrent read never sees a partial file.