neiam
/apollos_crib
It's Apollo's Crib
public · Issues · Pulls 1 · Labels · Forks · Compare · Actions failure · Badges · Packages
⭐
Log in to mark this repository.
Keryx: stop the show page crashing once a Keryx has seen anything
b1b7c62 · Gabriel Morell · 2026-10-05 22:40
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