Difference between revisions of "TaskFlow/StateFlow Pattern"
(→Operational description) |
|||
Line 16: | Line 16: | ||
subflow), consider this StateFlow executed or revert everything. | subflow), consider this StateFlow executed or revert everything. | ||
− | + | More precisely, when "state" finishes, it emits an event. Author of the flow | |
− | + | can bind any result subflow provides to be the event. The result should be | |
− | More precisely, when "state" finishes, it emits an event. | + | a string. There also can be a default catch-all transition. |
− | |||
− | |||
− | |||
− | |||
== Simple example == | == Simple example == | ||
Line 77: | Line 73: | ||
state node. That will require modification of graph analyzer. | state node. That will require modification of graph analyzer. | ||
− | === | + | == Q & A == |
− | |||
− | |||
− |
Revision as of 08:32, 6 May 2014
bp: https://blueprints.launchpad.net/taskflow/+spec/stateflow-pattern
StateFlow pattern is yet another idea how to implement conditional execution in TaskFlow.
Contents
Operational description
As any pattern, StateFlow combines several tasks and/or other patterns into new flow. Each subflow (be it other pattern or task) of StateFlow is considered to be a state (like in state machine). Only one "state" is active (has running tasks) at any moment when StateFlow is executed. When subflow is finished, a desision what to do next is made based on its results: should we switch to another "state" (execute another subflow), consider this StateFlow executed or revert everything.
More precisely, when "state" finishes, it emits an event. Author of the flow can bind any result subflow provides to be the event. The result should be a string. There also can be a default catch-all transition.
Simple example
flow = StateFlow('get user') welcome = WelcomeTask() lookup = FindExistingUserTask() create = make_create_user_flow() meta = AddUserMetadataTask()` save = SaveUserTask()
flow.add(welcome, lookup, create, save) flow.initial_state(welcome)
flow.on(welcome, 'SUCCESS', lookup) flow.on(lookup, 'SUCCESS', flow.FINISH) flow.on(lookup, 'FAILURE', create)
flow.set_event_variable(create, 'create_event') flow.on(create, 'SUCCESS', save) flow.on(create, 'NEEDS_META', meta)
flow.on(meta, 'SUCCESS', save) flow.on(save, 'SUCCESS', flow.FINISH)
When flow is executed, first we execute WelcomeTask. When it succeeds, we execute FindExistingUserTask (variable named `lookup`). If lookup is executed successfully, we found existing user, so we finish the flow. If lookup failed, we should create new user, using flow created by make_create_user_flow factory function. This flow provides result named 'create_event' which contains next event name. If that result (in storage) is string 'SUCCESS' after create is executed, we run SaveUserTask and finish flow; otherwise, if it is string 'NEEDS_META', we run AddUserMetadataTask, then SaveUserTask, then we finished.
Implementation Notes
No cycles
While many workflow engines permit cycles, we don't; StateFlow checks that there is no series of events that leads to cycles, and subflows always form DAG.
Requires and provides
Because states form DAG there is finite number of paths to go from StateFlow start to finish. For each of these paths set of provided values MUST be the same; StateFlow ensures that.
Implementation idea
Before and after each subflow special atoms are added; thus, each transition is about selecting one edge of several edges that go out of state node. That will require modification of graph analyzer.