defmodule Chaperon.Action.Async do @moduledoc """ Implementation module for asynchronous actions (function calls into a `Chaperon.Scenario` module). """ defstruct module: nil, function: nil, args: [], task_name: nil @type t :: %Chaperon.Action.Async{ module: module, function: atom, args: [any], task_name: atom } end defimpl Chaperon.Actionable, for: Chaperon.Action.Async do alias Chaperon.Session use Chaperon.Session.Logging def run( action = %{ module: mod, function: func_name, args: args, task_name: task_name }, session ) do session |> log_debug("Async #{task_name} : #{mod}.#{func_name}(#{inspect(args)})") task = action |> execute_task(session) session |> Session.add_async_task(task_name, task) |> Session.ok() end def abort(action, session) do {:ok, action, session} end defp execute_task( %{ module: mod, function: func_name, args: args, task_name: task_name }, session ) do session = session |> Session.fork() Task.async(fn -> session |> Session.time(task_name, fn sess -> apply(mod, func_name, [sess | args]) end) end) end end defimpl String.Chars, for: Chaperon.Action.Async do def to_string(%{module: mod, function: func_name, args: args}) do "Async[#{mod}.#{func_name}/#{Enum.count(args)}]" end end