Skip to content

Commit 5877a6e

Browse files
committed
Fix crash on error detail page when using MySQL/MariaDB
Instead of using `{:array, :string}` for the `:breakcrumbs` field in `ErrorTracker.Occurrence` we use a new custom field type `ErrorTracker.Types.StringArray`. It uses `Jason` to encode and decode arrays when storing and retrieving arrays. Therefore it works very similarly to the `:array` type but without crashing on retrieval when using MySQL/MariaDB. This fix does not make a schema migration necessary. An additional test module `ErrorTracker.StoreFetchTest` was implemented to avoid regreessions in the future. Fixes #150.
1 parent 99c3fb2 commit 5877a6e

File tree

3 files changed

+48
-1
lines changed

3 files changed

+48
-1
lines changed

lib/error_tracker/schemas/occurrence.ex

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ defmodule ErrorTracker.Occurrence do
1818
field :reason, :string
1919

2020
field :context, :map
21-
field :breadcrumbs, {:array, :string}
21+
field :breadcrumbs, ErrorTracker.Types.StringArray
2222

2323
embeds_one :stacktrace, ErrorTracker.Stacktrace
2424
belongs_to :error, ErrorTracker.Error
+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
defmodule ErrorTracker.Types.StringArray do
2+
@moduledoc """
3+
Custom Ecto type for lists.
4+
5+
The built-in `:array` type is not properly implemented for the Ecto adapter `Ecto.Adapters.MyXQL`.
6+
Therefore we can not use it and have to impelement our own.
7+
"""
8+
use Ecto.Type
9+
10+
def type, do: {:array, :string}
11+
12+
def cast(list) when is_list(list) do
13+
{:ok, list}
14+
end
15+
16+
def cast(_), do: :error
17+
18+
def load(list) when is_binary(list) do
19+
Jason.decode(list)
20+
end
21+
22+
def load(list), do: {:ok, list}
23+
24+
def dump(list) when is_list(list) do
25+
ErrorTracker.Repo.with_adapter(fn
26+
:mysql -> Jason.encode(list)
27+
_ -> {:ok, list}
28+
end)
29+
end
30+
31+
def dump(_), do: :error
32+
end
+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
defmodule ErrorTracker.StoreFetchTest do
2+
@moduledoc """
3+
Test if simple store-retrieve operations are successful.
4+
5+
This is necessary, because some Ecto adapters like `Ecto.Adapters.MyXQL` may successfully store a field, but crash on retrieval.
6+
"""
7+
use ErrorTracker.Test.Case
8+
9+
test "after reporting an error its occurrences should be retrievable from DB" do
10+
assert %ErrorTracker.Occurrence{id: occurrence_id} =
11+
report_error(fn -> raise "BOOM" end)
12+
13+
assert %ErrorTracker.Occurrence{} = repo().get!(ErrorTracker.Occurrence, occurrence_id)
14+
end
15+
end

0 commit comments

Comments
 (0)