Keryx: stop the show page crashing once a Keryx has seen anything

b1b7c62 · Gabriel Morell · 2026-10-05 22:40

11 files +92 -2
Message
{commit_body(@commit)}

Files changed

modified apps/room_sanctum/lib/room_sanctum_web/live/keryx_live/show.ex
+9 −2
@@ -35,11 +35,15 @@ defmodule RoomSanctumWeb.KeryxLive.Show do
35 35 {:noreply, assign(socket, :cached_items, cached_items)}
36 36 end
37 37
38 + # A cache that is not there, or is busy, is an exit rather than an
39 + # exception -- so caught, not rescued.
38 40 defp fetch_cached_items(keryx_id) do
39 41 try do
40 42 RoomSanctum.Worker.KeryxItemCache.get_all_items(keryx_id)
41 43 rescue
42 44 _ -> %{}
45 + catch
46 + :exit, _ -> %{}
43 47 end
44 48 end
45 49
@@ -53,9 +57,12 @@ defmodule RoomSanctumWeb.KeryxLive.Show do
53 57 def format_item_preview(data) do
54 58 try do
55 59 encoded = Jason.encode!(data, pretty: true)
56 − # Makeup returns an IO list, convert to string and mark as safe HTML
60 + # Makeup returns an IO list, convert to string and mark as safe HTML.
61 + # The lexer is named because the default is Elixir's, from makeup_elixir,
62 + # which this app does not have: left out, every preview raised, and the
63 + # page went down wherever a Keryx had seen anything at all.
57 64 encoded
58 − |> Makeup.highlight()
65 + |> Makeup.highlight(lexer: Makeup.Lexers.JsonLexer)
59 66 |> Phoenix.HTML.raw()
60 67 rescue
61 68 Protocol.UndefinedError ->
added apps/room_sanctum/test/room_sanctum_web/live/keryx_show_test.exs
+83 −0
@@ -0,0 +1,83 @@
1 +defmodule RoomSanctumWeb.KeryxShowTest do
2 + @moduledoc """
3 + The Keryx page, and whatever its worker has seen so far.
4 +
5 + Builds its own fixtures, as SourceLiveBulkPaintTest does, since
6 + ConfigurationFixtures predates the required user_id.
7 + """
8 + use RoomSanctumWeb.ConnCase
9 +
10 + import Phoenix.LiveViewTest
11 +
12 + alias RoomSanctum.{Accounts, Configuration}
13 +
14 + setup %{conn: conn} do
15 + {:ok, user} =
16 + Accounts.register_user(%{
17 + email: "herald#{System.unique_integer([:positive])}@example.com",
18 + password: "hello world!hello world!"
19 + })
20 +
21 + {:ok, source} =
22 + Configuration.create_source(%{
23 + name: "Markets",
24 + notes: "",
25 + type: :bourse,
26 + enabled: true,
27 + user_id: user.id,
28 + config: %{"__type__" => "bourse"}
29 + })
30 +
31 + {:ok, query} =
32 + Configuration.create_query(%{
33 + name: "AAPL",
34 + notes: "",
35 + source_id: source.id,
36 + user_id: user.id,
37 + query: %{"__type__" => "bourse", "symbol" => "AAPL"}
38 + })
39 +
40 + {:ok, keryx} =
41 + Configuration.create_keryx(%{
42 + name: "herald",
43 + ttl: 60,
44 + query_ids: [query.id],
45 + user_id: user.id
46 + })
47 +
48 + %{conn: log_in_user(conn, user), keryx: keryx}
49 + end
50 +
51 + # The page asks the Keryx's item cache what it has seen. That cache is a
52 + # process, and a process may not be there -- not started yet, or restarting
53 + # after its worker fell over -- which is an exit, not an exception.
54 + test "renders with no worker running", %{conn: conn, keryx: keryx} do
55 + assert {:ok, live, _html} = live(conn, "/cfg/keryxiae/#{keryx.id}")
56 +
57 + send(live.pid, :refresh_cache)
58 + assert render(live) =~ "herald"
59 + end
60 +end
61 +
62 +defmodule RoomSanctumWeb.KeryxItemPreviewTest do
63 + @moduledoc """
64 + The highlighted JSON beside each item the Keryx has seen.
65 +
66 + Dev rarely has any items, prod always does -- so a preview that cannot
67 + render takes the whole page down only where somebody is looking at it.
68 + """
69 + use ExUnit.Case, async: true
70 +
71 + alias RoomSanctumWeb.KeryxLive.Show
72 +
73 + test "highlights an item as JSON" do
74 + html = %{"route" => "14", "times" => ["08:00:00"]} |> Show.format_item_preview() |> Phoenix.HTML.safe_to_string()
75 +
76 + assert html =~ "route"
77 + assert html =~ "08:00:00"
78 + end
79 +
80 + test "falls back to inspect for what JSON cannot say" do
81 + assert Show.format_item_preview(%{at: {1, 2}}) =~ "{1, 2}"
82 + end
83 +end

Parents: 30a84b2