
Note: this is a conceptual, “how does the SWF design pattern work” article, rather than a “how-to”. In fact, implementation does not need to be Amazon specific, although SWF supports the pattern.
A Naive, Simple Code Example
We may write fairly complex algorithms to fulfill the needs of a complex process. One could write a single function that coordinates an activity such as processing an order. Our naive pseudo-code:
function processOrder(var orderInformation) { bool customer = verifyCustomerInfo(orderInformation); bool inventory = verifyInventory(orderInformation); bool payment = verifyCreditCard(orderInformation); bool shipment = scheduleShipment(orderInformation); bool notification = notify(orderInformation); }
Obviously, we would need to evaluate each step and apply logic along the way. Our processOrder function will quickly become fairly complex as we apply decision logic and have many nested “if this then that”.
In this example, Coordination and Decision are intermingled in the same function. As the complexity of possible outcomes increases, so does the code.
SWF Design Pattern
AWS SWF can help with coordination patterns such as the one above by giving certain elements very specific duties to perform, and by having those elements perform highly cohesive responsibilities of Coordination, Decision and Work.
Main elements of SWF:
- SWF (Coordinator)
- Decider
- Activity Workers
A Workflow Starter initiates the workflow lifecycle. From there, the remaining three elements perform specific duties in a cyclical pattern of SWF -> Decider -> SWF -> Activity Worker.
A generic pattern looks like this:
- SWF receives initiation, updates workflow history and schedules a decision task.
- Decider receives the task, evaluates history and decides the next Activity.
- SWF receives decision, then schedules an Activity, and waits for the completion of that Activity.
- The Activity Worker receives the task, executes it and returns to SWF.
- SWF receives the result, updates workflow history and schedules a decision task.
In the initial naive code example above, the processOrder function appears to have two responsibilities: Coordination and Decision. SWF will allow us to segregate those activities and have highly cohesive responsibilities.
SWF Conceptual Takeaways
- The cycle occurring n times is: SWF -> Decider -> SWF -> Activity Worker.
- Workflow History plays an important role and is recorded by SWF.
- Given Workflow History, we can amend this cyclic pattern in the following way:
- SWF (log history)
- Decider
- SWF (schedule activity)
- Activity Worker
- Updating History allows the Decider to decide appropriately.
- Each element receives. This implies sharing or passing of data/state.
- SWF itself, is a coordinator, and will NOT perform the work itself. It either calls the Decider or an Activity Worker.
- Activity Workers perform work.
- An Activity Worker is called by and returns results to SWF.
- Deciders decide which Activity is next, but the Decider does NOT call an Activity Worker directly.
- Deciders review history, evaluate it and decide the next Activity.
- The Decider can close a Workflow.