From b15376299fec6c77f4b363ec006363f3662937ca Mon Sep 17 00:00:00 2001 From: Everton Ribeiro Date: Sun, 1 Mar 2020 16:24:08 -0300 Subject: [PATCH 1/2] Add support to set timeout in run_async --- lib/journey.ex | 37 ++++++++++++++++++++----------------- test/journey_test.exs | 23 +++++++++++++++++++++++ 2 files changed, 43 insertions(+), 17 deletions(-) diff --git a/lib/journey.ex b/lib/journey.ex index 21b0c1d..ecbfac7 100644 --- a/lib/journey.ex +++ b/lib/journey.ex @@ -12,11 +12,11 @@ defmodule Journey do end def run(%__MODULE__{} = journey, spec, args \\ []) do - add_step(journey, spec, args, :sync) + add_step(journey, {spec, args}, :sync) end - def run_async(%__MODULE__{} = journey, spec, args \\ []) do - add_step(journey, spec, args, :async) + def run_async(%__MODULE__{} = journey, spec, args \\ [], timeout \\ 5000) do + add_step(journey, {spec, args, timeout}, :async) end def await(%__MODULE__{steps: steps} = journey) do @@ -25,11 +25,12 @@ defmodule Journey do |> check_results() end - def await(%Step{transaction: {func, %Task{} = task}} = step) do + def await(%Step{spec: {_, _, timeout}, transaction: {func, %Task{} = task}} = step) do result = - case Task.yield(task) do + case Task.yield(task, timeout) do {:ok, result} -> result {:exit, error} -> {:error, error} + nil -> {:error, {:timeout, step}} end %Step{step | transaction: {func, result}} @@ -45,28 +46,28 @@ defmodule Journey do finally(journey, fn %{result: result} -> result end) end - defp add_step(%__MODULE__{} = journey, spec, args, :sync = type) do + defp add_step(%__MODULE__{} = journey, spec, :sync = type) do journey |> await() - |> mk_step(spec, args, type) + |> mk_step(spec, type) |> await() end - defp add_step(%__MODULE__{} = journey, spec, args, type) do - mk_step(journey, spec, args, type) + defp add_step(%__MODULE__{} = journey, spec, type) do + mk_step(journey, spec, type) end - defp mk_step(%__MODULE__{state: :failed} = journey, _, _, _), do: journey + defp mk_step(%__MODULE__{state: :failed} = journey, _, _), do: journey - defp mk_step(%__MODULE__{} = journey, spec, args, type) do - {transaction, compensation} = get_funcs(spec, args) + defp mk_step(%__MODULE__{} = journey, spec, type) do + {transaction, compensation} = get_funcs(spec) update_steps( journey, journey.steps ++ [ %Step{ - spec: {spec, args}, + spec: spec, compensation: {compensation, nil}, transaction: {transaction, call(transaction, journey, type)} } @@ -93,14 +94,16 @@ defmodule Journey do end end - defp get_funcs({module, function_name}, args) do - apply(module, function_name, args) |> extract_funcs() - end + defp get_funcs({spec, args}), do: get_funcs({spec, args, 0}) - defp get_funcs(func, _) when is_function(func) do + defp get_funcs({func, _, _}) when is_function(func) do extract_funcs(func.()) end + defp get_funcs({{module, function_name}, args, _}) do + extract_funcs(apply(module, function_name, args)) + end + defp extract_funcs({transaction, compensation} = funcs) when is_valid_function(transaction) and is_valid_function(compensation), do: funcs diff --git a/test/journey_test.exs b/test/journey_test.exs index 4e503e9..d11f0b6 100644 --- a/test/journey_test.exs +++ b/test/journey_test.exs @@ -225,6 +225,29 @@ defmodule JourneyTest do } ] = steps end + + test "run compensation if await a async transaction ended with timeout", %{journey: journey} do + result = + journey + |> Journey.run_async({__MODULE__, :test_compensation}, [:ok]) + |> Journey.run_async({__MODULE__, :test_compensation}, [fn -> :timer.sleep(500) end], 50) + # Step will not add because before step will failed + |> Journey.run({__MODULE__, :test_compensation}, [:ok]) + + assert %Journey{result: error, state: :failed, steps: steps} = result + assert {:error, {:timeout, %Step{spec: {{__MODULE__, :test_compensation}, _, 50}}}} = error + + assert [ + %Step{ + transaction: {_, :ok}, + compensation: {_, :ok} + }, + %Step{ + transaction: {_, {:error, {:timeout, %Step{}}}}, + compensation: {_, nil} + } + ] = steps + end end def test_compensation(result) when is_function(result) do From 8d4143817181aee992de3dbed3ad4b7efe33db70 Mon Sep 17 00:00:00 2001 From: Everton Ribeiro Date: Sun, 1 Mar 2020 16:29:41 -0300 Subject: [PATCH 2/2] Update test/journey_test.exs Co-Authored-By: Felipe Piacsek --- test/journey_test.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/journey_test.exs b/test/journey_test.exs index d11f0b6..7078b60 100644 --- a/test/journey_test.exs +++ b/test/journey_test.exs @@ -231,7 +231,7 @@ defmodule JourneyTest do journey |> Journey.run_async({__MODULE__, :test_compensation}, [:ok]) |> Journey.run_async({__MODULE__, :test_compensation}, [fn -> :timer.sleep(500) end], 50) - # Step will not add because before step will failed + # Step will not be added because previous step has failed due to timeout |> Journey.run({__MODULE__, :test_compensation}, [:ok]) assert %Journey{result: error, state: :failed, steps: steps} = result