Introduction
Function-as-a-Service (FaaS) is a novel and compelling cloud computing concept that aids in achieving the "serverless" dream by just deploying, running, and managing granular code fragments and services without worrying about the infrastructure details and is charged per usage. If applications can be assembled using serverless architecture, they would experience numerous advantages over the traditional architectures, such as scalability, fine-grained billing, and low operational costs. However, adopting serverless is sometimes slow due to the complexity of orchestrating FaaS and the risk of "vendor lock-in" as application porting between vendors becomes challenging without considerable effort and cost.
A study performed by the authors ("Pattern-based Serverless Data Processing Pipeline using Function-as-a-Service (FaaS) Orchestration Systems") proposes a methodology for composing serverless applications using FaaS orchestrating systems with the help of enterprise integration and workflow patterns to produce reusable software design solutions that standardize the integration process, reduce development costs and improve code quality. A detailed description of 20 identified patterns using the problem first approach has been listed on this website. These patterns were then classified into three categories. The construct patterns define the essential components necessary for constructing the workflow. The control flow is responsible for workflow traversal, and finally, the function-specific are patterns that are implemented in the function.
We encourage users to evaluate the proposed methodology and contribute to the list of patterns. Currently, we have listed the corresponding patterns for three diverse state-of-the-art FaaS orchestration systems: AWS Step Functions (ASF), Zeebe, and Azure Durable Functions (ADF).
Patterns
1. Process Manager
Problem
How does the serverless workflow determine the path in which the message needs to flow if it consists of multiple functions and conditions?
Decision
The Process Manager acts as a central processing component for the system. As workflows are influenced by each step's output message, execution states need to be maintained, and based on the result; the succeeding component is invoked.
Source
Pattern
Enterprise Integration Pattern
Type
Construct
Synonyms
-
Mapping
How can the serverless workflow and its involved functions be executed/triggered?
External services or clients can invoke the serverless data processing workflow by an Event Message. Furthermore, Event Messages can be used to invoke other workflows or services. As functions are considered a black box, the Document Message containing the data structure message is the most optimum choice when communicating between internal states/functions.
Enterprise Integration Pattern Construct -
How are functions represented in a serverless workflow and connected?
With the Message Endpoint construct, the various functions do not need to be aware of the message formats, channel, or other functions present in the serverless workflow. The functions only need to be mindful that they will receive requests, and it just needs to process and send the acknowledgment/response back to the system
Enterprise Integration Pattern Construct -
How to decompose a task that performs complex processing into a series of separate elements that can be reused?
Pipes and Filters help in implementing complex processing in a granular, independent, resilient and sequential manner. Moreover, the fundamental building blocks of serverless workflows are functions, and each function in the pipeline is generally responsible for small transactions making this pattern style optimum.
Enterprise Integration Pattern Construct Sequence, Sequential routing, Serial Routing
How will the serverless workflow route the same message to several endpoints and process them differently? A Multicast pattern is used to model the execution of parallel flows/concurrency by sending a copy of the same message to multiple recipients without checking any conditions. Here all outgoing flows are executed at the same time. Enterprise Integration Pattern Control Flow Parallel Split, AND-Split, Parallel Routing, Fork
Functions must be orchestrated to adhere to a process flow to generate an error-free/desired output. How can the messages be routed to the correct workflow execution path within the workflow based on the message content? A Content-based Router helps in controlling the workflow based on the message content. Each outgoing flow connected from the router corresponds to a condition, and the flow with the satisfied condition is traversed. Based on the condition, one or many flows can be traversed. In this pattern, the router examines the message content using numerous criteria like fields, values, and conditions before routing to the appropriate path. Enterprise Integration Pattern Control Flow Exclusive Choice, XOR-Split, Conditional Routing, Switch, Decision, Selection and OR-Split
In a serverless workflow, certain functions have to be executed multiple times to produce the desired outcome. How can the workflow orchestrate a function to be reused when it needs to be triggered recursively? The Loop pattern is used to loop through the function multiple times Enterprise Integration Pattern Control Flow Arbitrary Cycles, Iteration, Cycle
There are situations during a workflow execution when it needs to be paused or delayed to wait for a response/acknowledgment from an external system. How can the workflow incorporate a delay or wait? The Delay pattern helps in waiting or delaying a function from executing. The delay/wait can be configured by setting a time/period. Enterprise Integration Pattern Control Flow
Business and operational/implementation logic must be as decoupled as possible to allow core business logic to remain simple? The ingestion and output logic need to be encapsulated in separate functions with the help of Message Gateway pattern and this pattern also helps in dividing messaging-specific implementation from the business logic code. Enterprise Integration Pattern Function Specific
How can the workflow simplify dealing with large messages and transmit only the essential data to the required functions? The Content Filter pattern simplifies the structure of the messages by removing irrelevant data. Enterprise Integration Pattern Function Specific
How can the workflow fetch additional data required by the functions to process the message? The Content Enricher pattern accesses external data source and augments the original message with the missing information. Enterprise Integration Pattern Function Specific
Functions that pass large payloads of data within the workflow can be terminated due to size limitations. How will the communication between functions be handled when large messages need to be passed within the workflow? Large fields are temporarily filtered in the source function and enriched in the destination function using the Claim Check pattern. The payload is stored in a persistent store, and a Claim Check is passed to the target component. Internally, Claim Check uses the Content Filter and Content Enricher pattern. The Content Filter pattern removes insignificant data from an output message leaving only essential information, thus simplifying its structure. The target function then uses the Content Enricher pattern to augment the received message with the missing information, usually with the help of an external data source. Enterprise Integration Pattern Function Specific
How can the output from each terminal function in the workflow branches be normalized, which otherwise would require having an additional normalization function? The Normalizer pattern helps solve this problem by ensuring that the messages produced from any branch confirm with a standard format that is understandable by the recipient component. In this pattern, each message is passed through a custom message translator so that the resulting messages match a standard format. Hence this pattern helps in preventing the creation and invoking of additional functions to handle this scenario. Enterprise Integration Pattern Function Specific
How can we effectively analyze and debug the flow of messages in a loosely coupled and granular system? The primary purpose of employing a serverless paradigm is to build loosely coupled and granular systems. However, building such systems induces the complexity of debugging and traceability as it is not intuitively possible to comprehend the flow of the message. This problem can be solved using the _Message History_ pattern, in which the system maintains the history of the message. Thus when a message fails to be processed in the system, the developer can trace back the steps and provide instant feedback and solution. Enterprise Integration Pattern Construct/Function Specific
How can the serverless workflow process multiple homogeneous records concurrently that are part of a single payload? A Splitter pattern helps split a single message into a sequence of sub-messages that can be processed individually. Likewise, the Aggregator pattern performs the contrary by collecting a complete set of related messages. Combining the two patterns simulates the MapReduce2 implementation, which can be used to split the array payload into smaller chunks that be processed in a parallel fashion and, more importantly, avoid payload limit issues. Enterprise Integration Pattern Function Specific Fan-out, Fan-in
How to terminate the workflow when no execution steps are remaining? The Implicit Termination pattern states that if there is no task to be performed, stop the workflow. [Russell et al. 2006a], [van der Aalst et al. 2003] Workflow Control-Flow Pattern Control Flow
If some tasks are alike, how do we abstract and represent them as a hierarchical and reusable model? Nested Workflows patterns help facilitate reusable workflows, abstracting complex logic, effective communication, and hierarchical and modular modeling. [Russell et al. 2006a], [van der Aalst et al. 2003] Workflow Control-Flow Pattern Control Flow
How can the serverless workflow handle external invocations from a service or a human-performed activity?
In the Callback pattern, the workflow pauses execution and waits until an appropriate response is received to proceed with the execution. These tasks can be human, service, or some response from an external process.
[Russell et al. 2006a], [van der Aalst et al. 2003] Workflow Control-Flow Pattern Control Flow / Function Specific
How can the system handle error exceptions that might occur in the workflow and manage them gracefully? The Error Handling pattern helps handle exceptions due to abnormal input or conditions and can retry the processing when needed. [Russell et al. 2006a], [van der Aalst et al. 2003] Workflow Control-Flow Pattern Control Flow / Function Specific
The Workflow Data pattern states that the data required for the whole workflow will be available to all functions. In this pattern, the shared libraries and packages are placed under the appropriate directory or vendor-specific offerings. Workflow Data Pattern Function Specific
The constructed artifacts available in this website is part of a study performed by the University of Groningen & Researchable B.V.
AWS Step Functions
ASF snippet:
{
"Comment":"ASF Template",
"StartAt":"Function",
"States":{
"Function":{
"Type":"Pass",
"End":true
}
}
}
Zeebe
Azure Durable Functions
2. Event and Document Message
Problem
Decision
Source
Pattern
Type
Synonyms
Mapping
AWS Step Functions
Zeebe
Azure Durable Functions
3. Message Endpoint
Problem
Decision
Source
Pattern
Type
Synonyms
Mapping
AWS Step Functions
ASF snippet:
{
"State":{
"Type":"Task",
"Resource":"arn:aws:states:::lambda:invoke",
"Parameters":{
"FunctionName":"arn:aws:lambda:REGION:ACCOUNT_ID:function:FUNCTION_NAME",
"Payload":{
"Input.$":"$"
}
},
"Next":"NEXT_STATE"
}
}
Zeebe
ASF snippet:
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:zeebe="http://camunda.org/schema/zeebe/1.0" id="Definitions_0dmi4p0" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Zeebe Modeler" exporterVersion="0.11.0">
<bpmn:process id="Zeebe_Process" name="Zeebe Model" isExecutable="true">
<bpmn:serviceTask id="ServiceTask_Lambda" name="Service Task">
<bpmn:extensionElements>
<zeebe:taskDefinition type="lambda" />
</bpmn:extensionElements>
</bpmn:serviceTask>
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Zeebe_Process">
<bpmndi:BPMNShape id="Activity_079frpn_di" bpmnElement="ServiceTask_Lambda">
<dc:Bounds x="160" y="80" width="100" height="80" />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>
Azure Durable Functions
ASF snippet:
const function = yield context.df.callActivity("Activity Function", "Payload")
4. Pipes and Filters
Problem
Decision
Source
Pattern
Type
Synonyms
Mapping
AWS Step Functions
ASF code snippet:
{
"Comment":"Pipes And Filter Pattern",
"StartAt":"State 1",
"States":{
"State 1":{
"Type":"Task",
"Resource":"arn:aws:states:::lambda:invoke",
"Parameters":{
"FunctionName":"arn:aws:lambda:REGION:ACCOUNT_ID:function:FUNCTION_NAME"
},
"Next":"State 2"
},
"State 2":{
"Type":"Task",
"Resource":"arn:aws:states:::lambda:invoke",
"Parameters":{
"FunctionName":"arn:aws:lambda:REGION:ACCOUNT_ID:function:FUNCTION_NAME"
},
"End":true
}
}
}
Zeebe
Azure Durable Functions
ASF snippet:
import * as df from "durable-functions"
module.exports = df.orchestrator(function* (context) {
try {
const function1Result = yield context.df.callActivity("function1", context.df.getInput())
const function2Result = yield context.df.callActivity("function2", function1Result)
const function3Result = yield context.df.callActivity("function3", function2Result)
return function3Result;
}
catch (error) {
console.error(error)
}
});
5. Multicast
Problem
Decision
Source
Pattern
Type
Synonyms
Mapping
AWS Step Functions
ASF code snippet:
{
"Comment":"Multicast Pattern",
"StartAt":"MulticastState",
"States":{
"MulticastState":{
"Type":"Parallel",
"Branches":[
{
"StartAt":"Function 1",
"States":{
"Function 1":{
"Type":"Pass",
"End":true
}
}
},
{
"StartAt":"Function 2",
"States":{
"Function 2":{
"Type":"Pass",
"End":true
}
}
}
],
"End":true
}
}
}
Zeebe
Azure Durable Functions
ADF code snippet:
const df = require("durable-functions");
module.exports = df.orchestrator(function* (context) {
const parallelTasks = [];
// Get input
const data = context.df.getInput()
// Perform parallel processing
parallelTasks.push(context.df.callActivity("function1", data));
parallelTasks.push(context.df.callActivity("function2", data));
const arrayParallelTasksResult = yield context.df.Task.all(parallelTasks);
return arrayParallelTasksResult
});
6. Content-based Router
Problem
Decision
Source
Pattern
Type
Synonyms
Mapping
AWS Step Functions
ASF code snippet:
{
"Comment":"Content-based Router",
"StartAt":"ChoiceState",
"States":{
"ChoiceState":{
"Type":"Choice",
"Choices":[
{
"Variable":"$.variable",
"BooleanEquals":true,
"Next":"Choice 1"
},
{
"Variable":"$.variable",
"BooleanEquals":false,
"Next":"Choice 2"
}
]
},
"Choice 1":{
"Type":"Task",
"Resource":"arn:aws:states:::lambda:invoke",
"Parameters":{
"FunctionName":"arn:aws:lambda:REGION:ACCOUNT_ID:function:FUNCTION_NAME",
"Payload":{
"Input.$":"$"
}
},
"End":true
},
"Choice 2":{
"Type":"Task",
"Resource":"arn:aws:states:::lambda:invoke",
"Parameters":{
"FunctionName":"arn:aws:lambda:REGION:ACCOUNT_ID:function:FUNCTION_NAME",
"Payload":{
"Input.$":"$"
}
},
"End":true
}
}
}
Zeebe
Azure Durable Functions
ADF code snippet:
const df = require("durable-functions");
module.exports = df.orchestrator(function* (context) {
var result
// Get input
const data = context.df.getInput()
// Perform parallel processing
if (data.isFunction1) {
result = yield context.df.callActivity("function1", data)
} else {
result = yield context.df.callActivity("function2", data)
}
return result
});
7. Loop
Problem
Decision
Source
Pattern
Type
Synonyms
Mapping
AWS Step Functions
ASF code snippet:
{
"Comment":"Loop",
"StartAt":"ChoiceState",
"States":{
"State 1":{
"Type":"Task",
"Resource":"arn:aws:states:::lambda:invoke",
"Parameters":{
"FunctionName":"arn:aws:lambda:REGION:ACCOUNT_ID:function:FUNCTION_NAME",
"Payload":{
"Input.$":"$"
}
},
"Next":"ChoiceState"
},
"ChoiceState":{
"Type":"Choice",
"Choices":[
{
"Variable":"$.variable",
"BooleanEquals":true,
"Next":"CompletedState"
}
],
"Default":"State 1"
},
"CompletedState":{
"Type":"Pass",
"End":true
}
}
}
While, the below figure and code snippet shows how the same Loop construct has been realized using a "Do-While" logic.
ASF code snippet:
{
"Comment":"Loop",
"StartAt":"State 1",
"States":{
"State 1":{
"Type":"Task",
"Resource":"arn:aws:states:::lambda:invoke",
"Parameters":{
"FunctionName":"arn:aws:lambda:REGION:ACCOUNT_ID:function:FUNCTION_NAME",
"Payload":{
"Input.$":"$"
}
},
"Next":"ChoiceState"
},
"ChoiceState":{
"Type":"Choice",
"Choices":[
{
"Variable":"$.variable",
"BooleanEquals":true,
"Next":"PassState"
}
],
"Default":"State 1"
},
"PassState":{
"Type":"Pass",
"End":true
}
}
}
Zeebe
Azure Durable Functions
ADF code snippet:
const df = require("durable-functions");
module.exports = df.orchestrator(function* (context) {
var result
// Get input
const data = context.df.getInput()
// Loop till condition is false
while (data.loopCondition) {
result = yield context.df.callActivity("function1", data)
}
return result
});
8. Delay
Problem
Decision
Source
Pattern
Type
Synonyms
Mapping
AWS Step Functions
ASF code snippet:
{
"Comment":"Wait",
"StartAt":"State 1",
"States":{
"State 1":{
"Type":"Task",
"Resource":"arn:aws:states:::lambda:invoke",
"Parameters":{
"FunctionName":"arn:aws:lambda:REGION:ACCOUNT_ID:function:FUNCTION_NAME",
"Payload":{
"Input.$":"$"
}
},
"Next":"WaitState"
},
"WaitState":{
"Type":"Wait",
"Seconds":10,
"End":true
}
}
}
Zeebe
Azure Durable Functions
ADF code snippet:
const df = require("durable-functions");
const moment = require("moment");
module.exports = df.orchestrator(function* (context) {
const function1Result = yield context.df.callActivity("function1", context.df.getInput())
// Perform delay operation
const delay = moment.utc(context.df.currentUtcDateTime).add(30, "s");
yield context.df.createTimer(delay.toDate())
const function2Result = yield context.df.callActivity("function2", function1Result)
return function2Result
});
9. Gateway
Problem
Decision
Source
Pattern
Type
Synonyms
Mapping
AWS Step Functions
ASF code snippet:
// Import Gateway Logic
const lambdaGateway = require("/opt/utility/lambda_gateway.js");
exports.lambdaHandler = async (event, context, callback) => {
// Input Gateway logic
const event = lambdaGateway.inputGateway(event, context);
// Start : Business logic
// End : Business logic
// Output Gateway logic
lambdaGateway.outputGateway(JSON.stringify(event), callback);
};
Zeebe
Azure Durable Functions
10. Content Filter
Problem
Decision
Source
Pattern
Type
Synonyms
Mapping
AWS Step Functions
Users have the added benefit of performing the entire filtering or code-specific filtering using custom-developed filters through AWS Lambdas, shown by the below code snippet.
ASF code snippet:
// Import utils
const lambdaGateway = require("/opt/utility/utlis.js");
exports.lambdaHandler = async (event, context, callback) => {
// Input Gateway logic
const data = lambdaGateway.inputGateway(event, context);
// Start : Business logic
// Content Filter logic - Users can follow custom logic
const transformedData = utils.removeField(data, ["field_1", "field_2"]);
// End : Business logic
// Output Gateway logic
lambdaGateway.outputGateway(JSON.stringify(transformedData), callback);
};
Zeebe
Azure Durable Functions
ADF code snippet:
const df = require("durable-functions");
const utils = require("../utility/utils.js");
module.exports = df.orchestrator(function* (context) {
var function1Result = yield context.df.callActivity("function1", context.df.getInput())
// Start : Filter result
function1Result = utils.removeField(function1Result,'parameter1')
// End : Filter result
const function2Result = yield context.df.callActivity("function2", function1Result)
return function2Result
});
11. Content Enricher
Problem
Decision
Source
Pattern
Type
Synonyms
Mapping
AWS Step Functions
For complex Content Enricher scenarios, the below code snippet presents how the user can implement custom fetch and enrich message logic through AWS S3.
ASF code snippet:
// Import required libraries
const lambdaGateway = require("/opt/utility/utlis.js");
const s3Operation = require("/opt/utility/aws_s3_service.js");
exports.lambdaHandler = async (event, context, callback) => {
// Input Gateway logic
const data = lambdaGateway.inputGateway(event, context);
// Start : Business logic
// Content Enricher logic - Users can follow custom logic
// Fetch data from data source
const new_data = await s3Operation.getPayload("key", "bucketName");
// Append data
const transformedData = utils.addNewField(data, {
new_field: new_data,
});
// End : Business logic
// Output Gateway logic
lambdaGateway.outputGateway(JSON.stringify(transformedData), callback);
};
Zeebe
Azure Durable Functions
ADF code snippet:
const df = require("durable-functions");
const utils = require("../utility/utils.js");
module.exports = df.orchestrator(function* (context) {
var function1Result = yield context.df.callActivity("function1", context.df.getInput())
var function2Result = yield context.df.callActivity("function2", context.df.getInput())
// Start : Enrich result
function1Result = utils.addNewField(function1Result, function2Result)
// End : Enrich result
const function3Result = yield context.df.callActivity("function3", function1Result)
return function3Result
});
12. Claim Check
Problem
Decision
Source
Pattern
Type
Synonyms
Mapping
AWS Step Functions
Zeebe
Azure Durable Functions
13. Normalizer
Problem
Decision
Source
Pattern
Type
Synonyms
Mapping
AWS Step Functions
Zeebe
Azure Durable Functions
14. Message History
Problem
Decision
Source
Pattern
Type
Synonyms
Mapping
AWS Step Functions
Zeebe
Azure Durable Functions
15. Splitter and Aggregator
Problem
Decision
Source
Pattern
Type
Synonyms
Mapping
AWS Step Functions
ASF snippet:
{
"Comment":"Callback",
"StartAt":"MapState",
"States":{
"MapState":{
"Type":"Map",
"ItemsPath":"$.array",
"MaxConcurrency":0,
"Iterator":{
"StartAt":"State 1",
"States":{
"State 1":{
"Type":"Pass",
"Result":"Done!",
"End":true
}
}
},
"ResultPath":"$.output",
"End":true
}
}
}
Zeebe
Azure Durable Functions
ADF code snippet:
const df = require("durable-functions");
module.exports = df.orchestrator(function* (context) {
const mapTasks = [];
// Get a list of batches to process in parallel
const batch = yield context.df.callActivity("function1");
// Perform parallel processing of the batches (Map)
for (let i = 0; i < batch.length; i++) {
mapTasks.push(context.df.callActivity("function2", batch[i]));
}
const arrayParallelTasksResult = yield context.df.Task.all(mapTasks);
// Aggregate the results (Reduce)
yield context.df.callActivity("function3", arrayParallelTasksResult);
});
16. Implicit Termination
Problem
Decision
Source
Pattern
Type
Synonyms
Mapping
AWS Step Functions
The below figure and code snippet presents an example how the Implicit Termination pattern is achieved by ASF.
ASF snippet:
{
"Comment":"Implicit Termination",
"StartAt":"State 1",
"States":{
"State 1":{
"Type":"Task",
"Resource":"arn:aws:states:::lambda:invoke",
"Parameters":{
"FunctionName":"arn:aws:lambda:REGION:ACCOUNT_ID:function:FUNCTION_NAME",
"Payload":{
"Input.$":"$"
}
},
"Next":"ChoiceState"
},
"ChoiceState":{
"Type":"Choice",
"Choices":[
{
"Variable":"$.variable",
"BooleanEquals":true,
"Next":"SuccessState"
},
{
"Variable":"$.variable",
"BooleanEquals":false,
"Next":"OtherState"
}
]
},
"SuccessState":{
"Type":"Succeed"
},
"OtherState":{
"Type":"Task",
"Resource":"arn:aws:states:::lambda:invoke",
"Parameters":{
"FunctionName":"arn:aws:lambda:REGION:ACCOUNT_ID:function:FUNCTION_NAME",
"Payload":{
"Input.$":"$"
}
},
"End":true
}
}
}
Zeebe
Azure Durable Functions
ADF code snippet:
const df = require("durable-functions");
module.exports = df.orchestrator(function* (context) {
const function1Result = yield context.df.callActivity("function1", context.df.getInput())
return function1Result
});
17. Nested Workflows
Problem
Decision
Source
Pattern
Type
Synonyms
Mapping
AWS Step Functions
ASF snippet:
{
"Comment":"Nested Workflow",
"StartAt":"Start state machine execution",
"States":{
"Start state machine execution":{
"Type":"Task",
"Resource":"arn:aws:states:::states:startExecution",
"Parameters":{
"StateMachineArn":"arn:aws:states:REGION:ACCOUNT_ID:stateMachine:STATE_MACHINE_NAME",
"Input":{
"StatePayload":"Hello from Step Functions!",
"AWS_STEP_FUNCTIONS_STARTED_BY_EXECUTION_ID.$":"$$.Execution.Id"
}
},
"End":true
}
}
}
Zeebe
Azure Durable Functions
ADF code snippet:
const df = require("durable-functions");
module.exports = df.orchestrator(function* (context) {
const result = context.df.callSubOrchestrator("subOrchestration", context.df.getInput())
return result
});
18. Callback
Problem
Decision
Source
Pattern
Type
Synonyms
Mapping
AWS Step Functions
ASF snippet:
{
"Comment":"Callback",
"StartAt":"Step 1",
"States":{
"Step 1":{
"Type":"Task",
"Resource":"arn:aws:states:::lambda:invoke.waitForTaskToken",
"Parameters":{
"FunctionName":"arn:aws:lambda:REGION:ACCOUNT_ID:function:FUNCTION_NAME",
"Payload":{
"Input.$":"$",
"TaskToken.$":"$$.Task.Token"
}
},
"End":true
}
}
}
Zeebe
Azure Durable Functions
ADF code snippet:
const df = require("durable-functions");
module.exports = df.orchestrator(function* (context) {
const token = yield context.df.waitForExternalEvent("externalFunction");
if (token) {
// token received from external and continue processing
} else {
// token failed
}
});
19. Error Handling
Problem
Decision
Source
Pattern
Type
Synonyms
Mapping
AWS Step Functions
ASF snippet:
{
"Comment":"Nested Workflow",
"StartAt":"Step 1",
"States":{
"Step 1":{
"Type":"Task",
"Resource":"arn:aws:states:::lambda:invoke",
"Parameters":{
"FunctionName":"arn:aws:lambda:REGION:ACCOUNT_ID:function:FUNCTION_NAME",
"Payload":{
"Input.$":"$"
}
},
"Catch":[
{
"ErrorEquals":[
"States.TaskFailed"
],
"Next":"NotifyError"
}
],
"Retry":[
{
"ErrorEquals":[
"States.Timeout"
],
"IntervalSeconds":3,
"MaxAttempts":2,
"BackoffRate":1.5
}
],
"End":true
},
"NotifyError":{
"Type":"Fail",
"Cause":"Invalid response.",
"Error":"ErrorA"
}
}
}
Zeebe
Azure Durable Functions
ADF code snippet:
const df = require("durable-functions");
module.exports = df.orchestrator(function* (context) {
try {
const function1 = yield context.df.callActivity("function1", context.df.getInput())
return function1;
}
catch (error) {
console.error(error)
}
});
20. Workflow Data
Problem
Decision
Source
Pattern
Type
Synonyms
Mapping
AWS Step Functions
Zeebe
Azure Durable Functions
ADF code snippet:
References
Contributors