With AWS Step Functions, you can easily orchestrate serverless functions and sequence them with other AWS services to a bundle application. You can create AWS Step Functions with CloudFormation, the AWS Cloud Development Kit, or - of course - using the visual interface available in the AWS Management Console. This post shows how to orchestrate AWS Lambda functions to a simple State Machine using AWS Step Functions.
AWS Lambda Function with CDK
The AWS Cloud Development Kit simplifies a couple of things. One is creating an AWS Lambda function with inline code. For this example, create two lambda functions: One for generating a random string and one function to reverse the provided input:
const functionGenerateID = new lambda.Function(this, "GenerateID", {
runtime: lambda.Runtime.NODEJS_12_X,
handler: "index.handler",
code: lambda.Code.fromInline(`
const generate = () => Math.random().toString(36).substring(7);
exports.handler = async () => ({"value": generate()});
`),
});
const functionReverseID = new lambda.Function(this, "ReverseID", {
runtime: lambda.Runtime.NODEJS_12_X,
handler: "index.handler",
code: lambda.Code.fromInline(`
const reverse = (str) => (str === '') ? '' : reverse(str.substr(1)) + str.charAt(0);
exports.handler = async (state) => ({"value": reverse(state.value)});
`),
});
AWS Step Functions with CDK
For AWS Step Functions, the AWS Cloud Development Kit offers a few helper functions to easily configure individual steps.
First, the State Machine invokes an AWS Lambda function to create a random string. The next step waits for a second. Aftward the second function reverses the generated string.
const first = new tasks.LambdaInvoke(this, "Generate ID", {
lambdaFunction: functionGenerateID,
outputPath: "$.Payload",
})
.next(
new sfn.Wait(this, "Wait 1 Second", {
time: sfn.WaitTime.duration(cdk.Duration.seconds(1)),
})
)
.next(
new tasks.LambdaInvoke(this, "Reverse ID", {
lambdaFunction: functionReverseID,
outputPath: "$.Payload",
})
);
State Machine with AWS Step Functions
As a CDK Construct, both code samples together look like this:
import * as cdk from "@aws-cdk/core";
import * as lambda from "@aws-cdk/aws-lambda";
import * as sfn from "@aws-cdk/aws-stepfunctions";
import * as tasks from "@aws-cdk/aws-stepfunctions-tasks";
export class StateMachine extends cdk.Construct {
public Machine: sfn.StateMachine;
constructor(scope: cdk.Construct, id: string) {
super(scope, id);
const functionGenerateID = new lambda.Function(this, "GenerateID", {
runtime: lambda.Runtime.NODEJS_12_X,
handler: "index.handler",
code: lambda.Code.fromInline(`
const generate = () => Math.random().toString(36).substring(7);
exports.handler = async () => ({"value": generate()});
`),
});
const functionReverseID = new lambda.Function(this, "ReverseID", {
runtime: lambda.Runtime.NODEJS_12_X,
handler: "index.handler",
code: lambda.Code.fromInline(`
const reverse = (str) => (str === '') ? '' : reverse(str.substr(1)) + str.charAt(0);
exports.handler = async (state) => ({"value": reverse(state.value)});
`),
});
const definition = new tasks.LambdaInvoke(this, "Generate ID", {
lambdaFunction: functionGenerateID,
outputPath: "$.Payload",
})
.next(
new sfn.Wait(this, "Wait 1 Second", {
time: sfn.WaitTime.duration(cdk.Duration.seconds(1)),
})
)
.next(
new tasks.LambdaInvoke(this, "Reverse ID", {
lambdaFunction: functionReverseID,
outputPath: "$.Payload",
})
);
this.Machine = new sfn.StateMachine(this, "StateMachine", {
definition,
timeout: cdk.Duration.minutes(5),
});
}
}