| « PreviousNext » | |
![]() ![]() ![]() | Did this page help you? Yes | No | Tell us about it... |
Topics
In some scenarios, you might want to schedule a different set of activities based on the outcome of a previous activity. The exclusive choice pattern enables you to create flexible workflows that meet the complex requirements of your application.
The Amazon Simple Workflow Service (Amazon SWF) does not have a specific exclusive choice action. To use exclusive choice, you simply write your decider logic to make different decisions based on the results of the previous activity. Some applications for exclusive choice include the following:
Performing cleanup activities if the results of a previous activity were unsuccessful
Scheduling different activities based on whether the customer purchased a basic or advanced plan
Performing different customer authentication activities based on the customer's ordering history
In the e-commerce example, you might use exclusive choice to either ship or cancel an order based on the outcome of charging the credit card. In the following figure, the decider schedules the Ship Order and Record Completion activity tasks if the credit card is successfully charged. Otherwise, it schedules the Cancel Order and Email Customer activity tasks.

The decider schedules the ShipOrder activity if the credit card is
successfully charged. Otherwise, the decider schedules the CancelOrder
activity.
In this case, program the decider to interpret the history and determine whether the credit card was successfully charged. To do this, you might have logic similar to the following
IF lastEvent = "WorkflowExecutionStarted"
addToDecisions ScheduleActivityTask(ActivityType = "VerifyOrderActivity")
ELSIF lastEvent = "ActivityTaskCompleted"
AND ActivityType = "VerifyOrderActivity"
addToDecisions ScheduleActivityTask(ActivityType = "ChargeCreditCardActivity")
#Successful Credit Card Charge Activities
ELSIF lastEvent = "ActivityTaskCompleted"
AND ActivityType = "ChargeCreditCardActivity"
addToDecisions ScheduleActivityTask(ActivityType = "ShipOrderActivity")
ELSIF lastEvent = "ActivityTaskCompleted"
AND ActivityType = "ShipOrderActivity"
addToDecisions ScheduleActivityTask(ActivityType = "RecordOrderCompletionActivity")
ELSIF lastEvent = "ActivityTaskCompleted"
AND ActivityType = "RecordOrderCompletionActivity"
addToDecisions CompleteWorkflowExecution
#Unsuccessful Credit Card Charge Activities
ELSIF lastEvent = "ActivityTaskFailed"
AND ActivityType = "ChargeCreditCardActivity"
addToDecisions ScheduleActivityTask(ActivityType = "CancelOrderActivity")
ELSIF lastEvent = "ActivityTaskCompleted"
AND ActivityType = "CancelOrderActivity"
addToDecisions ScheduleActivityTask(ActivityType = "EmailCustomerActivity")
ELSIF lastEvent = "ActivityTaskCompleted"
AND ActivityType = "EmailCustomerActivity"
addToDecisions CompleteWorkflowExecution
ENDIFIf the credit card was successfully charged, the decider should respond with
RespondDecisionTaskCompleted to schedule the ShipOrder activity.
https://swf.us-east-1.amazonaws.com
RespondDecisionTaskCompleted
{
"taskToken": "12342e17-80f6-FAKE-TASK-TOKEN32f0223",
"decisions":[
{
"decisionType":"ScheduleActivityTask",
"scheduleActivityTaskDecisionAttributes":{
"control":"OPTIONAL_DATA_FOR_DECIDER",
"activityType":{
"name":"ShipOrder",
"version":"2.4"
},
"activityId":"3e2e6e55-e7c4-fee-deed-aa815722b7be",
"scheduleToCloseTimeout":"3600",
"taskList":{
"name":"SHIPPING"
},
"scheduleToStartTimeout":"600",
"startToCloseTimeout":"3600",
"heartbeatTimeout":"300",
"input": "123 Main Street, Anytown, United States"
}
}
]
}If the credit card was not successfully charged, the decider should respond with RespondDecisionTaskCompleted to schedule the
CancelOrder activity.
https://swf.us-east-1.amazonaws.com
RespondDecisionTaskCompleted
{
"taskToken": "12342e17-80f6-FAKE-TASK-TOKEN32f0223",
"decisions":[
{
"decisionType":"ScheduleActivityTask",
"scheduleActivityTaskDecisionAttributes":{
"control":"OPTIONAL_DATA_FOR_DECIDER",
"activityType":{
"name":"CancelOrder",
"version":"2.4"
},
"activityId":"3e2e6e55-e7c4-fee-deed-aa815722b7be",
"scheduleToCloseTimeout":"3600",
"taskList":{
"name":"CANCELLATIONS"
},
"scheduleToStartTimeout":"600",
"startToCloseTimeout":"3600",
"heartbeatTimeout":"300",
"input": "Out of Stock"
}
}
]
}If Amazon SWF is able to validate the data in the RespondDecisionTaskCompleted action, Amazon SWF returns a successful HTTP response
similar to the following.
HTTP/1.1 200 OK Content-Length: 11 Content-Type: application/json x-amzn-RequestId: 93cec6f7-0747-11e1-b533-79b402604df1
A timer enables you to notify your decider when a certain amount of time has elapsed. When
responding to a decision task, the decider has the option to respond with a StartTimer
decision. This decision specifies an amount of time after which the timer should fire. After the
specified time has elapsed, Amazon SWF will add a TimerFired event to the workflow
execution history and schedule a decision task. The decider can then use this information to inform
further decisions. One common application for a timer is to delay the execution of an activity task.
For example, a customer might want to take delayed delivery of an item.
Signals enable you to inform a workflow execution of external events and inject information
into a workflow execution while it is running. Any program can send a signal to a running
workflow execution by calling the SignalWorkflowExecution API.
When a signal is received, Amazon SWF records it in the workflow execution's history as
WorkflowExecutionSignaled event and alerts the decider by scheduling a
decision task.
Note
An attempt to send a signal to a workflow execution that is not open results in
SignalWorkflowExecution failing with UnknownResourceFault.
In this example, the workflow execution is sent a signal to cancel an order.
https://swf.us-east-1.amazonaws.com
SignalWorkflowExecution
{"domain": "867530901",
"workflowId": "20110927-T-1",
"runId": "f5ebbac6-941c-4342-ad69-dfd2f8be6689",
"signalName": "CancelOrder",
"input": "order 3553"}If the workflow execution receives the signal, Amazon SWF returns a successful HTTP response similar to the following. Amazon SWF will generate a decision task to inform the decider to process the signal.
HTTP/1.1 200 OK Content-Length: 0 Content-Type: application/json x-amzn-RequestId: bf78ae15-3f0c-11e1-9914-a356b6ea8bdf
Sometimes you might want to wait for a signal. For example, a user could cancel an order by
sending a signal, but only within one hour of placing the order. Amazon SWF does not have a
primitive to enable a decider to wait for a signal from the service. Pause functionality needs
to be implemented in the decider itself. In order to pause, the decider should start a timer,
using the StartTimer decision, which specifies the duration
for which the decider will wait for the signal while continuing to poll for decision tasks.
When the decider receives a decision task, it should check the history to see if either the
signal has been received or the timer has fired. If the signal has been received, then the
decider should cancel the timer. However, if instead, the timer has fired, then it means that
the signal did not arrive within the specified time. To summarize, in order to wait for a
specific signal, do the following.
Create a timer for the amount of time the decider should wait.
When a decision task is received, check the history to see if the signal has arrived or if the timer has fired.
If a signal has arrived, cancel the timer using a CancelTimer decision and process the signal. Depending on the timing, the
history may contain both TimerFired and
WorkflowExecutionSignaled events. In such cases, you can rely on the
relative order of the the events in the history to determine which occurred
first.
If the timer has fired, before a signal is received, then the decider has timed out waiting for the signal. You can fail the execution or do whatever other logic is appropriate to your use case.
Activity task cancellation enables the decider to end activities that no longer need to be performed. Amazon SWF uses a cooperative cancellation mechanism and does not forcibly interrupt running activity tasks. You must program your activity workers to handle cancellation requests.
The decider can decide to cancel an activity task while it is processing a decision task. To
cancel an activity task, the decider uses the RespondDecisionTaskCompleted action with the RequestCancelActivityTask decision.
If the activity task has not yet been acquired by an activity worker, the service will cancel the task. Note that there is a potential race condition in that an activity worker could acquire the task at any time. If the task has already been assigned to an activity worker, then the activity worker will be requested to cancel the task.
In this example, the workflow execution is sent a signal to cancel the order.
https://swf.us-east-1.amazonaws.com
SignalWorkflowExecution
{"domain": "867530901",
"workflowId": "20110927-T-1",
"runId": "9ba33198-4b18-4792-9c15-7181fb3a8852",
"signalName": "CancelOrder",
"input": "order 3553"}If the workflow execution receives the signal, Amazon SWF returns a successful HTTP response similar to the following. Amazon SWF will generate a decision task to inform the decider to process the signal.
HTTP/1.1 200 OK Content-Length: 0 Content-Type: application/json x-amzn-RequestId: 6c0373ce-074c-11e1-9083-8318c48dee96
When the decider processes the decision task and sees the signal in the history, the decider attempts to cancel the outstanding activity that has the ShipOrderActivity0001 activity ID. The activity ID is provided in the workflow history from the schedule activity task event.
https://swf.us-east-1.amazonaws.com
RespondDecisionTaskCompleted
{
"taskToken":"12342e17-80f6-FAKE-TASK-TOKEN32f0223",
"decisions":[{
"decisionType":"RequestCancelActivityTask",
"RequestCancelActivityTaskDecisionAttributes":{
"ActivityID":"ShipOrderActivity0001"
}
}
]
}If Amazon SWF successfully receives the cancellation request, it returns a successful HTTP response similar to the following:
HTTP/1.1 200 OK Content-Length: 0 Content-Type: application/json x-amzn-RequestId: 6c0373ce-074c-11e1-9083-8318c48dee96
The cancellation attempt is recorded in the history as the ActivityTaskCancelRequested event.
If the task is successfully canceled—as indicated by an ActivityTaskCanceled event—program your decider to take the appropriate steps
that should follow task cancellation such as closing the workflow execution.
If the activity task could not be canceled—for example, if the task completes, fails, or times out instead of canceling—your decider should accept the results of the activity or perform any cleanup or mitigation necessitated by your use case.
If the activity task has already been acquired by an activity worker, then the request to
cancel is transmitted through the task-heartbeat mechanism. Activity workers can periodically
use RecordActivityTaskHeartbeat to report to Amazon SWF that the
task is still in progress.
Note that activity workers are not required to heartbeat, although it is recommended for long-running tasks. Task cancellation requires periodic heartbeat to be recorded; if the worker does not heartbeat, the task cannot be canceled.
If the decider requests a cancellation of the task, Amazon SWF sets the value of the cancelRequest object to true. The cancelRequest
object is part of the ActivityTaskStatus object which is returned by
the service in response to RecordActivityTaskHeartbeat.
Amazon SWF does not prevent the successful completion of an activity task whose cancellation has been requested; it is up to the activity to determine how to handle the cancellation request. Depending on your requirements, program the activity worker to either cancel the activity task or ignore the cancellation request.
If you want the activity worker to indicate that the work for the activity task was canceled,
program it to respond with a RespondActivityTaskCanceled. If you want
the activity worker to complete the task, program it to respond with a standard RespondActivityTaskCompleted.
When Amazon SWF receives the RespondActivityTaskCompleted or RespondActivityTaskCanceled request, it updates the workflow execution
history and schedules a decision task to inform the decider.
Program the decider to process the decision task and return any additional decisions. If the activity task is successfully canceled, program the decider to perform the tasks needed to continue or close the workflow execution. If the activity task is not successfully canceled, program the decider to accept the results, ignore the results, or schedule any required cleanup.
You can use markers to record events in the workflow execution history for application specific purposes. Markers are useful when you want to record custom information to help implement decider logic. For example, you could use a marker to count the number of loops in a recursive workflow.
In the following example, the decider completes a decision task and responds with a RespondDecisionTaskCompleted
action that contains a RecordMarker decision.
https://swf.us-east-1.amazonaws.com
RespondDecisionTaskCompleted
{
"taskToken":"12342e17-80f6-FAKE-TASK-TOKEN32f0223",
"decisions":[{
"decisionType":"RecordMarker",
"recordMarkerDecisionAttributes":{
"markerName":"customer elected special shipping offer"
}
},
]
}If Amazon SWF successfully records the marker, it returns a successful HTTP response similar to the following.
HTTP/1.1 200 OK Content-Length: 0 Content-Type: application/json x-amzn-RequestId: 6c0373ce-074c-11e1-9083-8318c48dee96
Recording a marker does not, by itself, initiate a decision task. To prevent the workflow execution from becoming stuck, something must occur that continues the execution of the workflow. For example, this might include the decider scheduling another activity task, the workflow execution receiving a signal, or a previously scheduled activity task completing.
As described in the section Tags,
you can associate up to five tags with a workflow execution when you start the execution
using the StartWorkflowExecution action, StartChildWorkflowExecution
decision, or ContinueAsNewWorkflowExecution decision. Tagging enables you to filter your results
when you use visibility actions to list or count workflow executions.
To use tagging
Devise a tagging strategy. Think about your business requirements and create a list of tags that are meaningful to you. Determine which executions will get which tags. Even though an execution can be assigned a maximum of five tags, your tag library can have any number of tags. Because each tag can be any string value up to 256 characters in length, a tag can describe almost any business concept.
Tag an execution with up to five tags when you create it.
List or count the executions that are tagged with a particular tag by specifying the
tagFilter parameter with the ListOpenWorkflowExecutions,
ListClosedWorkflowExecutions, CountOpenWorkflowExecutions, and
CountClosedWorkflowExecutions actions. The action will filter the executions
based on the tags specified.
When you associate a tag with a workflow execution, it is permanently associated with that execution, and cannot be removed.
You can specify only one tag in the tagFilter parameter
with ListWorkflowExecutions. Also, tag matching is case sensitive,
and only exact matches return results.
Assume you have already set up two executions that are tagged as follows.
| Execution Name | Assigned Tags |
|---|---|
|
Execution-One |
Consumer, 2011-February |
|
Execution-Two |
Wholesale, 2011-March |
You can filter the list of executions returned by ListOpenWorkflowExecutions
on the Consumer tag. The oldestDate and latestDate
values are specified as Unix Time values.
https://swf.us-east-1.amazonaws.com
RespondDecisionTaskCompleted
{
"domain":"867530901",
"startTimeFilter":{
"oldestDate":1262332800,
"latestDate":1325348400
},
"tagFilter":{
"tag":"Consumer"
}
}