recipe v0.1.0 Recipe behaviour View Source

Intro

The Recipe module allows implementing multi-step, reversible workflows.

For example, you may wanna parse some incoming data, write to two different data stores and then push some notifications. If anything fails, you wanna rollback specific changes in different data stores. Recipe allows you to do that.

Core ideas

  • A workflow is a state machine
  • Each step can have a specific error handling scenario
  • Each step is a separate function that receives a state with the result of all previous steps

Example

defmodule Example do
  use Recipe

  ### Public API

  def run(number) do
    state = Recipe.empty_state
            |> Recipe.assign(:number, number)

    Recipe.run(__MODULE__, state)
  end

  ### Callbacks

  def steps, do: [:square, :double]

  def handle_result(state) do
    {:ok, state.assigns.number}
  end

  def handle_error(_step, _error, _state), do: :cannot_fail

  ### Steps

  def square(state) do
    number = state.assigns.number
    {:ok, Recipe.assign(state, :number, number*number)}
  end

  def double(state) do
    number = state.assigns.number
    {:ok, Recipe.assign(state, :number, number * 2)}
  end
end

Link to this section Summary

Functions

Assigns a new value in the recipe state under the specified key

Returns an empty recipe state. Useful in conjunction with Recipe.run/2

Runs a recipe, identified by a module which implements the Recipe behaviour

Runs a recipe, identified by a module which implements the Recipe behaviour, also allowing to specify the initial state

Callbacks

Invoked any time a step fails. Receives the name of the failed step, the error and the state

Invoked at the end of the recipe, it receives the state obtained at the last step

Lists all steps included in the recipe, e.g. [:square, :double]

Link to this section Types

Link to this type error() View Source
error() :: term
Link to this type recipe_module() View Source
recipe_module() :: atom

Link to this section Functions

Link to this function assign(state, key, value) View Source
assign(Recipe.State.t, atom, term) :: Recipe.State.t

Assigns a new value in the recipe state under the specified key.

Keys are available for reading under the assigns key.

Link to this function empty_state() View Source
empty_state() :: Recipe.State.t

Returns an empty recipe state. Useful in conjunction with Recipe.run/2.

Link to this function run(recipe_module) View Source
run(recipe_module) :: {:ok, term} | {:error, term}

Runs a recipe, identified by a module which implements the Recipe behaviour.

Link to this function run(recipe_module, initial_state) View Source
run(recipe_module, Recipe.State.t) ::
  {:ok, term} |
  {:error, term}

Runs a recipe, identified by a module which implements the Recipe behaviour, also allowing to specify the initial state.

Link to this section Callbacks

Link to this callback handle_error(step, error, arg2) View Source
handle_error(step, error, Recipe.State.t) :: term

Invoked any time a step fails. Receives the name of the failed step, the error and the state.

Link to this callback handle_result(arg0) View Source
handle_result(Recipe.State.t) :: term

Invoked at the end of the recipe, it receives the state obtained at the last step.

Lists all steps included in the recipe, e.g. [:square, :double]