Toolbox.Workflow (toolbox v1.1.0)
Module provides API to define state machine based workflow. Workflow is represented by struct containing all configuration needed to handle state of individual instances of given workflow.
Workflow is defined by transitions, which contains all needed attributes (source node, target
node, ..). Workflow defined by transitions needs to be built epxlicitly by calling build/1
function. This function validates all workflow dependencies and state machine structure.
Workflow definition produced by build/1
function can be used to create new instance of given
workflow. Workflow instance is struct of:
- unique id
- status
- state (map containing all relevant data, manipulated by then callback during status transition)
- history (record of all transitions which given instance went through in the past)
- history in default is map of
%{"timestamp" => timestamp, "status" => binary}
- history entry can be updated via update_history_entry callback defined in transition
- possible transitions (list of all transitions which could be executed in close future)
possible transition in default is map of
%{"timestamp" => -1 | timestamp, "status" => binary}
- timestamp -1 represents non-timeoutable transition
- possible transition entry can be updated via update_possible_transition callback defined in transition
Workflow transition can be defined by:
- from (source status)
- to (target status)
- when (predicate used to select transition which will be executed)
- there can be multiple when definitions in list, all definitions are connected with && relation
- possible when definitions:
{Module, function}
, where function accepts transition, instance and message as args{:timeout, timeout}
, where timeout is defined in milliseconds{:=, [path, to, state, key], value}
{:>, [path, to, state, key], value}
{:<, [path, to, state, key], value}
{:<=, [path, to, state, key], value}
{:>=, [path, to, state, key], value}
{:contains, [path, to, state, key], value}
{:is_in, [path, to, state, key], list_value}
- all callbacks should return boolean value
- then (callback used to update workflow instance state during transition execution)
- there can be multiple then definitions in list, all definitions are executed in given order
- possible then definitions:
{Module, function}
, where funciton accepts transition, instance and message as args
all calbacks should return
{:ok, %{} = wf_instance_state} | {:error, reason}
- side_effects (callback used to generate output actions during transition execution)
- there can be multiple then definitions in list, all definitions are executed in given order
- possible then definitions:
{Module, function}
, where funciton accepts transition, instance and message as args
all calbacks should return
{:ok, [OutputAction]} | {:error, reason}
- update_history_entry (callback used to modify transition execution history entry)
- there can be multiple then definitions in list, all definitions are executed in given order
- possible then definitions:
{Module, function}
, where funciton accepts history entry, transition, instance and message as args
all calbacks should return
{:ok, %{} = updated_history_entry} | {:error, reason}
- update_possible_transition (callback used in
handle_message/3
to modify possible transition)- there can be multiple then definitions in list, all definitions are executed in given order
- possible then definitions:
{Module, function}
, where funciton accepts possible transtion, transition, instance and message as args
all calbacks should return
{:ok, %{} = updated_possible_transition} | {:error, reason}
Workflow transition execution uses given workflow definition and message to update state of given instance. If no configured workflow transition matches, nothing will happend = instance state will remain the same.
Order of callback execution:
- when definitions of transitions in definition order
- then definitions of matching transition
- update history entry definitions of matching transition
- update possible transition definitions of matching transition
- side effects definitions of matching transition
Link to this section Summary
Functions
Workflow transition can be defined by keys in params
Finishes workflow definition, validates all configured dependencies and workflow structure
Uses given workflow definition and message to update state of given instance. If no configured workflow transition matches, nothing will happend = instance state will remain the same.
Creates new blank workflow definition
Creates new instance for given workflow
Link to this section Types
status()
@type status() :: String.t()
@type t() :: %Toolbox.Workflow{ built?: boolean(), statuses: [status()], terminal_statuses: [status()], transitions: transitions() }
transitions()
@type transitions() :: %{required(status()) => [Toolbox.Workflow.Transition.t()]}
Link to this section Functions
add_transition(wf, params)
Workflow transition can be defined by keys in params:
- from (source status)
- required parameter
- to (target status)
- required parameter
- when (predicate used to select transition which will be executed)
- optional parameter
- there can be multiple when definitions in list, all definitions are connected with && relation
- possible when definitions:
{Module, function}
, where function accepts transition, instance and message as args{:timeout, timeout}
, where timeout is defined in milliseconds{:=, [path, to, state, key], value}
{:>, [path, to, state, key], value}
{:<, [path, to, state, key], value}
{:<=, [path, to, state, key], value}
{:>=, [path, to, state, key], value}
{:contains, [path, to, state, key], value}
{:is_in, [path, to, state, key], list_value}
- all callbacks should return boolean value
- then (callback used to update workflow instance state during transition execution)
- optional parameter
- there can be multiple then definitions in list, all definitions are executed in given order
- possible then definitions:
{Module, function}
, where funciton accepts transition, instance and message as args
all calbacks should return
{:ok, %{} = wf_instance_state} | {:error, reason}
- side_effects (callback used to generate output actions during transition execution)
- optional parameter
- there can be multiple then definitions in list, all definitions are executed in given order
- possible then definitions:
{Module, function}
, where funciton accepts transition, instance and message as args
all calbacks should return
{:ok, [OutputAction]} | {:error, reason}
- update_history_entry (callback used to modify transition execution history entry)
- optional parameter
- there can be multiple then definitions in list, all definitions are executed in given order
- possible then definitions:
{Module, function}
, where funciton accepts history entry, transition, instance and message as args
all calbacks should return
{:ok, %{} = updated_history_entry} | {:error, reason}
- update_possible_transition (callback used in
handle_message/3
to modify possible transition)- optional parameter
- there can be multiple then definitions in list, all definitions are executed in given order
- possible then definitions:
{Module, function}
, where funciton accepts possible transtion, transition, instance and message as args
all calbacks should return
{:ok, %{} = updated_possible_transition} | {:error, reason}
build(wf)
@spec build(t()) :: {:ok, t()} | {:error, :transition_from_required} | {:error, :transition_to_required} | {:error, {:bad_callback, {atom(), atom()}}} | {:error, :multiple_init_statuses}
Finishes workflow definition, validates all configured dependencies and workflow structure
handle_message(workflow, message)
@spec handle_message(t(), Toolbox.Message.t()) :: {:ok, [Toolbox.Scenario.OutputAction.t()], Toolbox.Workflow.Instance.t()} | {:terminated, [Toolbox.Scenario.OutputAction.t()], Toolbox.Workflow.Instance.t()} | {:error, :not_built_yet} | {:error, :status_mismatch}
Uses given workflow definition and message to update state of given instance. If no configured workflow transition matches, nothing will happend = instance state will remain the same.
Order of callback execution:
- when definitions of transitions in definition order
- then definitions of matching transition
- update history entry definitions of matching transition
- update possible transition definitions of matching transition
- side effects definitions of matching transition
handle_message(wf, wf_inst, msg)
new()
@spec new() :: t()
Creates new blank workflow definition
new_instance(wf, status, id, state, msg, options \\ [])
@spec new_instance(t(), status(), String.t(), map(), Toolbox.Message.t(), Keyword.t()) :: {:ok, [Toolbox.Scenario.OutputAction.t()], Toolbox.Workflow.Instance.t()} | {:terminated, [Toolbox.Scenario.OutputAction.t()], Toolbox.Workflow.Instance.t()} | {:error, :unknown_status}
Creates new instance for given workflow