Jido.Exec
(Jido Action v2.0.0)
View Source
Action 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(), jido: atom()]
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.{:error, %Jido.Action.Error.InvalidInputError{}}when awaited by a non-owner process.
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.{:error, %Jido.Action.Error.InvalidInputError{}}when cancelled by a non-owner process.
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].:jido- Optional instance name for isolation. Routes execution through instance-scoped supervisors (e.g.,MyApp.Jido.TaskSupervisor).
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.:owner- The PID of the caller that started the async 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"}}