View Source Pipeline behaviour (ex_pipeline v0.2.0)

Pipeline definition and execution.

what-is-a-pipeline

What is a "pipeline"?

A pipeline is set of functions that must be executed in a specific order to transform an initial state into a desired state. For example, a "login pipeline" uses the request body as its initial state and generates an authentication token.

creating-a-pipeline

Creating a pipeline

To create a new feature as a pipeline, you can simply use Pipeline in the target module and start writing functions: steps and hooks.

pipeline-steps

Pipeline Steps

  • Steps are executed in the same order that they are declared in the module.
  • Any function that ends with _step and accepts two parameters is considered a step in the pipeline.
  • A step accepts a value and must return an ok tuple with the updated value or an error tuple with the error description. If one step failes, the following steps are not executed.
    • The first parameter is the value that's being transformed by each step
    • The second parameter are optional values and it's immutable

pipeline-hooks

Pipeline Hooks

  • Hooks are executed in the same order that they are declared in the module.
  • Any function that ends with _hook and accepts two parameters is considered a hook in the pipeline.
  • Hooks receive the final state of the pipeline, and they are always executed after all steps.
    • The first parameter is the final state as defined by the %Pipeline.State{} struct.
    • The second parameter are optional values and it's immutable, the same used by the steps.

async-hooks

Async Hooks

  • They're just like hooks, but the function name must end with _async_hook
  • They are launched on isolated processes to processed asynchronously, after all steps are done and before the hooks start being executed.

example

Example

defmodule StringToNumber do
  use Pipeline

  def detect_binary_step(value, _options) do
    cond do
      is_binary(value) ->
        {:ok, value}

      true ->
        {:error, "Not a string"}
    end
  end

  def cleanup_step(value, _options) do
    {:ok, String.trim(value)}
  end

  def parse_step(value, _options) do
    case Float.parse(value) do
      {number, _} ->
        {:ok, number}

      :error ->
        {:error, "Invalid number"}
    end
  end
end

To execute this pipeline, you can use StringToNumber.execute/2 or Pipeline.execute/3

Link to this section Summary

Callbacks

Returns a list of tuple with three elements.

Functions

Executes the pipeline defined by module with the given value and options.

Link to this section Callbacks

@callback __pipeline__() ::
  {[Pipeline.Types.reducer()], [Pipeline.Types.hook()],
   [Pipeline.Types.async_hook()]}

Returns a list of tuple with three elements.

The first element is a list of functions to be used as steps of a pipeline. These steps will be executed in the same order that they appear on this list.

The second element is a list of functions to be used as hooks of a pipeline. These hooks will be executed in the same order that they appear on this list.

The third element is a list of functions to be used as async hooks of a pipeline. The order of execution is not guaranteed.

Link to this section Functions

Link to this function

execute(module, value, options \\ [])

View Source

Executes the pipeline defined by module with the given value and options.

First, all steps are executed in the same order that they were declared on their module. If one step fails, all the steps that come after it will not be executed. The returned value from one step will be passed to the next step, along with the given options.

Then all async hooks are triggered and executed asynchronously in their own process. They will receive the final %Pipeline.State{} along with the given options. Their return values are ignored.

After that, all hooks are executed in the same order that they were declared on their module. They will receive the final %Pipeline.State{} along with the given options. Their return values are ignored.

Once steps and hooks are executed, the state is evaluated and then this function will returns an ok or error tuple, depending wether or not the state is valid.

If the given module does not implement the required callbacks from Pipeline behaviour, a PipelineError will be thrown.