Jido.Exec (Jido Action v2.0.0-rc.0)
View SourceAction execution engine with modular architecture for robust action processing.
This module provides the core execution interface for Jido Actions with specialized helper modules handling specific concerns:
- Jido.Exec.Validator - Parameter and output validation
- Jido.Exec.Telemetry - Logging and telemetry events
- Jido.Exec.Retry - Exponential backoff and retry logic
- Jido.Exec.Compensation - Error handling and compensation
- Jido.Exec.Async - Asynchronous execution management
- Jido.Exec.Chain - Sequential action execution
- Jido.Exec.Closure - Action closures with pre-applied context
Core Features
- Synchronous and asynchronous action execution
- Automatic retries with exponential backoff
- Timeout handling for long-running actions
- Parameter and context normalization
- Comprehensive error handling and compensation
- Telemetry integration for monitoring and tracing
- Action cancellation and cleanup
Usage
Basic action execution:
Jido.Exec.run(MyAction, %{param1: "value"}, %{context_key: "context_value"})Asynchronous execution:
async_ref = Jido.Exec.run_async(MyAction, params, context)
# ... do other work ...
result = Jido.Exec.await(async_ref)See Jido.Action for how to define an Action.
Summary
Functions
Waits for the result of an asynchronous Action execution.
Awaits the completion of an asynchronous Action with a custom timeout.
Cancels a running asynchronous Action execution.
Executes a Action synchronously with the given parameters and context.
Executes a Action asynchronously with the given parameters and context.
Types
@type action() :: module()
@type context() :: map()
@type exec_error() :: {:error, Exception.t()}
@type exec_error_dir() :: {:error, Exception.t(), any()}
@type exec_result() :: exec_success() | exec_success_dir() | exec_error() | exec_error_dir()
@type exec_success() :: {:ok, map()}
@type params() :: map()
@type run_opts() :: [{:timeout, non_neg_integer()}]
Functions
@spec await(async_ref()) :: exec_result()
Waits for the result of an asynchronous Action execution.
Parameters
async_ref: The reference returned byrun_async/4.timeout: Maximum time (in ms) to wait for the result (default: 5000).
Returns
{:ok, result}if the Action executes successfully.{:error, reason}if an error occurs during execution or if the action times out.
Examples
iex> async_ref = Jido.Exec.run_async(MyAction, %{input: "value"})
iex> Jido.Exec.await(async_ref, 10_000)
{:ok, %{result: "processed value"}}
iex> async_ref = Jido.Exec.run_async(SlowAction, %{input: "value"})
iex> Jido.Exec.await(async_ref, 100)
{:error, %Jido.Action.Error{type: :timeout, message: "Async action timed out after 100ms"}}
@spec await(async_ref(), timeout()) :: exec_result()
Awaits the completion of an asynchronous Action with a custom timeout.
Parameters
async_ref: The async reference returned byrun_async/4.timeout: Maximum time to wait in milliseconds.
Returns
{:ok, result}if the Action completes successfully.{:error, reason}if an error occurs or timeout is reached.
@spec cancel(async_ref() | pid()) :: :ok | exec_error()
Cancels a running asynchronous Action execution.
Parameters
async_ref: The reference returned byrun_async/4, or just the PID of the process to cancel.
Returns
:okif the cancellation was successful.{:error, reason}if the cancellation failed or the input was invalid.
Examples
iex> async_ref = Jido.Exec.run_async(LongRunningAction, %{input: "value"})
iex> Jido.Exec.cancel(async_ref)
:ok
iex> Jido.Exec.cancel("invalid")
{:error, %Jido.Action.Error{type: :invalid_async_ref, message: "Invalid async ref for cancellation"}}
@spec run(Jido.Instruction.t()) :: exec_result()
Executes a Action synchronously with the given parameters and context.
Parameters
action: The module implementing the Action behavior.params: A map of input parameters for the Action.context: A map providing additional context for the Action execution.opts: Options controlling the execution::timeout- Maximum time (in ms) allowed for the Action to complete (configurable via:jido_action, :default_timeout).:max_retries- Maximum number of retry attempts (configurable via:jido_action, :default_max_retries).:backoff- Initial backoff time in milliseconds, doubles with each retry (configurable via:jido_action, :default_backoff).:log_level- Override the global Logger level for this specific action. Accepts [:error, :info, :debug, :emergency, :alert, :critical, :warning, :notice].
Action Metadata in Context
The action's metadata (name, description, category, tags, version, etc.) is made available
to the action's run/2 function via the context parameter under the :action_metadata key.
This allows actions to access their own metadata when needed.
Returns
{:ok, result}if the Action executes successfully.{:error, reason}if an error occurs during execution.
Examples
iex> Jido.Exec.run(MyAction, %{input: "value"}, %{user_id: 123})
{:ok, %{result: "processed value"}}
iex> Jido.Exec.run(MyAction, %{invalid: "input"}, %{}, timeout: 1000)
{:error, %Jido.Action.Error{type: :validation_error, message: "Invalid input"}}
iex> Jido.Exec.run(MyAction, %{input: "value"}, %{}, log_level: :debug)
{:ok, %{result: "processed value"}}
# Access action metadata in the action:
# defmodule MyAction do
# use Jido.Action,
# name: "my_action",
# description: "Example action",
# vsn: "1.0.0"
#
# def run(_params, context) do
# metadata = context.action_metadata
# {:ok, %{name: metadata.name, version: metadata.vsn}}
# end
# end
@spec run(action(), params(), context(), run_opts()) :: exec_result()
Executes a Action asynchronously with the given parameters and context.
This function immediately returns a reference that can be used to await the result or cancel the action.
Note: This approach integrates with OTP by spawning tasks under a Task.Supervisor.
Make sure {Task.Supervisor, name: Jido.Action.TaskSupervisor} is part of your supervision tree.
Parameters
action: The module implementing the Action behavior.params: A map of input parameters for the Action.context: A map providing additional context for the Action execution.opts: Options controlling the execution (same asrun/4).
Returns
An async_ref map containing:
:ref- A unique reference for this async action.:pid- The PID of the process executing the Action.
Examples
iex> async_ref = Jido.Exec.run_async(MyAction, %{input: "value"}, %{user_id: 123})
%{ref: #Reference<0.1234.5678>, pid: #PID<0.234.0>}
iex> result = Jido.Exec.await(async_ref)
{:ok, %{result: "processed value"}}