Search documentation of Orchid

# Orchid.Step behaviour (Orchid v0.3.3)

View Source

Defines the behavior and specification for a workflow step.

A `Step` is the atomic unit of work in Orchid. It is responsible for receiving data (wrapped in `Orchid.Param`), performing a specific task, and returning new data.

### Usage

To define a step, `use Orchid.Step` and implement the `run/2` callback:

    defmodule MySteps.Upcase do
      use Orchid.Step
      alias Orchid.Param

      @impl true
      def run(input_param, _opts) do
        payload = Param.get_payload(input_param)

        result =
          Param.new(:result, :string)
          |> Param.set_payload(String.upcase(payload))

        {:ok, result}
      end
    end

### Input Pattern Matching

The structure of the `input` argument in `run/2` depends on how you define the input keys in your Recipe:

- Single Key: If input is `:my_data`, `run/2` receives a single `%Param{}`.
- List of Keys: If input is `[:a, :b]`, `run/2` receives a list `[%Param{}, %Param{}]`.
- Tuple of Keys: If input is `{:a, :b}`, `run/2` receives a tuple `{%Param{}, %Param{}}`.

### Step Options

Options can be passed when defining the step in a recipe or injected dynamically. Reserved options include:

- `:extra_hooks_stack` - A list of additional hooks to run for this specific step.
- `:__reporter_ctx__` - A map contains telemetry meta used by `report/3` to send progress updates.

# Summary

## Types

implementation()

The implementation of a step.

input()
input_keys()
io_key()
output()
output_keys()
step_options()

Options passed to the step execution context.

step_schema()

The schema definition of a step within a recipe. Format: `{Implementation, InputKeys, OutputKeys}`.

step_with_options()

A fully qualified step definition including options. Format: `{Implementation, InputKeys, OutputKeys, Options}`.

t()

## Callbacks

nested?()

Determines if this step contains an inner recipe (Nested Step). Defaults to `false`.

run(input, step_options)

Executes the step logic.

validate_options(step_options)

Validates the options passed to the step before execution.

## Functions

ensure_full_step(arg)

Normalizes a step structure into the full 4-element tuple format.

extract_schema(arg)

Extracts the basic schema `{Impl, Input, Output}` from a step definition.

inject_options(step, options)

Injects or merges options into a step definition.

# Types

# implementation()

    @type implementation() :: module() | function() | nil

The implementation of a step.

- `module()`: A module that implements the `Orchid.Step` behavior.

- `function()`: A function `fn input, opts -> {:ok, params} | {:error, term} end`.

# input()

    @type input() :: tuple() | Orchid.Param.t() | [Orchid.Param.t()]

# input_keys()

    @type input_keys() :: io_key()

# io_key()

    @type io_key() :: atom() | [atom()] | tuple() | MapSet.t()

# output()

    @type output() :: tuple() | Orchid.Param.t() | [Orchid.Param.t()]

# output_keys()

    @type output_keys() :: io_key()

# step_options()

    @type step_options() :: keyword()

Options passed to the step execution context.

# step_schema()

    @type step_schema() :: {implementation(), input_keys(), output_keys()}

The schema definition of a step within a recipe. Format: `{Implementation, InputKeys, OutputKeys}`.

# step_with_options()

    @type step_with_options() ::
      {implementation(), input_keys(), output_keys(), step_options()}

A fully qualified step definition including options. Format: `{Implementation, InputKeys, OutputKeys, Options}`.

# t()

    @type t() :: step_schema() | step_with_options()

# Callbacks

# nested?()

    @callback nested?() :: boolean()

Determines if this step contains an inner recipe (Nested Step). Defaults to `false`.

# run(input, step_options)

    @callback run(input(), step_options()) :: {:ok, output()} | {:error, term()}

Executes the step logic.

## Arguments

- `input` - The input parameters. Structure depends on `input_keys` definition.
- `opts` - The keyword list of options available to this step.

## Return Values

- `{:ok, output}` - Execution succeeded. `output` must match the structure of `output_keys`.
- `{:error, reason}` - Execution failed. The step (and potentially the workflow) halts.

# validate_options(step_options)

    @callback validate_options(step_options()) :: :ok | {:error, term()}

Validates the options passed to the step before execution.

This is useful for checking required configuration keys (e.g., API tokens, thresholds). Returns `:ok` if valid, or `{:error, reason}` otherwise.

# Functions

# ensure_full_step(arg)

    @spec ensure_full_step(t()) :: step_with_options()

Normalizes a step structure into the full 4-element tuple format.

If no options are present, an empty list is added.

# extract_schema(arg)

    @spec extract_schema(t()) :: step_schema()

Extracts the basic schema `{Impl, Input, Output}` from a step definition.

# inject_options(step, options)

    @spec inject_options(
      t(),
      keyword()
    ) :: step_with_options()

Injects or merges options into a step definition.

Supports both 3-element tuple (Schema) and 4-element tuple (Full Step).