berrypod/lib/berrypod_web/plugs/broken_url_tracker.ex
jamey 5e70c07b60
All checks were successful
deploy / deploy (push) Successful in 3m46s
persist mockup variants on fly volume across deploys
Source mockup WebPs are copied from the release to /data/mockups/
on startup, and variants are generated there. This eliminates the
182-job storm on every deploy that was saturating the CPU and
causing SQLite locking. After the first successful run, subsequent
deploys find all variants intact.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 11:20:33 +00:00

42 lines
1.2 KiB
Elixir

defmodule BerrypodWeb.Plugs.BrokenUrlTracker do
@moduledoc """
Wraps the router to record 404s in the broken URLs table.
Works in dev mode too — Plug.Debugger intercepts exceptions before
error templates render, so we catch NoRouteError here, record it,
then re-raise so the normal error handling continues.
"""
@behaviour Plug
def init(opts) do
router = Keyword.fetch!(opts, :router)
router_opts = router.init([])
{router, router_opts}
end
def call(conn, {router, router_opts}) do
router.call(conn, router_opts)
rescue
e in Phoenix.Router.NoRouteError ->
unless static_path?(conn.request_path) do
prior_hits = Berrypod.Analytics.count_pageviews_for_path(conn.request_path)
Berrypod.Redirects.record_broken_url(conn.request_path, prior_hits)
if prior_hits > 0 do
Berrypod.Redirects.attempt_auto_resolve(conn.request_path)
end
end
reraise e, __STACKTRACE__
end
defp static_path?(path) do
String.starts_with?(path, "/assets/") or
String.starts_with?(path, "/images/") or
String.starts_with?(path, "/image_cache/") or
String.starts_with?(path, "/mockups/") or
String.starts_with?(path, "/favicon")
end
end