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
_stepand 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
_hookand 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.
- The first parameter is the final state as defined by the
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
endTo 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
@spec execute(module(), Pipeline.Types.args(), Pipeline.Types.options()) :: Pipeline.Types.result()
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.