Skip to content

Commit a0ea80c

Browse files
authored
fix: Add stacktrace to exception (#265)
* fix: Add stacktrace to exception When an exception occured inside of a Reactor.Step it would not show the stacktrace but only the error message. This change includes the stacktrace in the exception and also adds a test that validates this * fix: remove rescue statement inside AnonFn.run/3 This prevented the stacktrace from being passed down to the executor. --------- Co-authored-by: Rutger <[email protected]>
1 parent c72cf38 commit a0ea80c

File tree

4 files changed

+49
-10
lines changed

4 files changed

+49
-10
lines changed

lib/reactor/executor/step_runner.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ defmodule Reactor.Executor.StepRunner do
161161
|> handle_run_result(reactor, step, arguments, context)
162162
rescue
163163
reason ->
164-
error = RunStepError.exception(step: step, error: reason)
164+
error = RunStepError.exception(step: step, error: reason, stacktrace: __STACKTRACE__)
165165
Hooks.event(reactor, {:run_error, error}, step, context)
166166

167167
maybe_compensate(reactor, step, error, arguments, context)

lib/reactor/step/anon_fn.ex

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@ defmodule Reactor.Step.AnonFn do
2929
{m, f, a} when is_atom(m) and is_atom(f) and is_list(a) ->
3030
apply(m, f, [arguments, context] ++ a)
3131
end
32-
rescue
33-
error -> {:error, error}
3432
end
3533

3634
@doc false

test/reactor/step/anon_fn_test.exs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,6 @@ defmodule Reactor.Step.AnonFnTest do
1919
test "it can handle an MFA" do
2020
assert :marty = run(%{first_name: :marty}, %{}, run: {__MODULE__, :example, []})
2121
end
22-
23-
test "it rescues errors" do
24-
fun = fn _, _ -> raise "Marty" end
25-
26-
assert {:error, error} = run(%{}, %{}, run: fun)
27-
assert Exception.message(error) =~ "Marty"
28-
end
2922
end
3023

3124
def example(arguments, _context) do

test/reactor/step/error_test.exs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
defmodule Reactor.Step.ErrorTest do
2+
@moduledoc false
3+
use ExUnit.Case, async: true
4+
5+
defmodule ErrorStep do
6+
@moduledoc false
7+
use Reactor.Step
8+
9+
@impl true
10+
def run(_argument, _context, _options) do
11+
raise "This step always returns an error"
12+
end
13+
end
14+
15+
defmodule ErrorReactor do
16+
@moduledoc false
17+
use Reactor
18+
19+
step :named_step, ErrorStep
20+
end
21+
22+
defmodule AnonErrorReactor do
23+
@moduledoc false
24+
use Reactor
25+
26+
step :step do
27+
run fn _, _ ->
28+
raise "This always returns an error"
29+
end
30+
end
31+
end
32+
33+
test "it has stacktrace available in error" do
34+
{:error, %{errors: [%{stacktrace: stacktrace}]}} = Reactor.run(ErrorReactor, %{})
35+
[{ErrorStep, :run, 3, opts} | _] = stacktrace.stacktrace
36+
37+
assert Keyword.get(opts, :line) == 11
38+
assert Keyword.get(opts, :file) == ~c"test/reactor/step/error_test.exs"
39+
end
40+
41+
test "it has stacktrace available when running anonymous step" do
42+
{:error, %{errors: [%{stacktrace: stacktrace}]}} = Reactor.run(AnonErrorReactor, %{})
43+
[{AnonErrorReactor, _anon_fn_name, _arity, opts} | _] = stacktrace.stacktrace
44+
45+
assert Keyword.get(opts, :line) == 28
46+
assert Keyword.get(opts, :file) == ~c"test/reactor/step/error_test.exs"
47+
end
48+
end

0 commit comments

Comments
 (0)