#✅ - Are there any examples of adding step functions in Amplify Gen2?

10 messages · Page 1 of 1 (latest)

amber jewel
#

Hi,

I found one example/tutorial to add step functions in Gen1
https://github.com/aws-samples/amplify-cdkv2-stepfunctions

Wondering if there is similar example for Gen2.
If not, could anyone summarize what changes are required in above tutorial to make it work with Gen2.

Also, any info on how to connect step function to event bridge using using Gen2 would be helpful.

The idea is for each new customer we will schedule some steps(lambda function) to be run on a hourly frequency, until the account is deactivated or deleted.
So a new scheduler should be created via code whenever new customer signs up and deleted via code whenever customer deletes their account.

Thanks

GitHub

Contribute to aws-samples/amplify-cdkv2-stepfunctions development by creating an account on GitHub.

junior isle
#

I think adding a custom CDK stack is pretty much the same for Gen 2. I found the documentation for it here: https://docs.amplify.aws/nextjs/build-a-backend/add-aws-services/custom-resources/

Once you add the StepFunctions stack in the custom folder like in the example you have linked (change Stack to Construct), you can instantiate it in the backend.ts file like this:

new ExampleStateMachine(
  backend.createStack('ExampleStateMachine'),
  'ExampleStateMachine',
);
chrome cipher
#

In Gen 2, you can use CDK to create a Step Function in amplify/backend.ts.

First import:

import * as sfn from 'aws-cdk-lib/aws-stepfunctions'
import * as tasks from 'aws-cdk-lib/aws-stepfunctions-tasks'

You can create a state machine in four steps:

Step 1: Define one or more task states. Each task is a single unit of work for the state machine to perform.

Let say you want to create a task state for invoking a Lambda function:

const function1Task = new tasks.LambdaInvoke(stack, 'Function1', {
  lambdaFunction: task1LambdaFunction,
  outputPath: '$.Payload.body',
})

task1LambdaFunction is defined using the defineFunction() in the resource.ts.

If you need the state machine's flow such as Succeed, Fail, etc., you can use new sfn.Succeed(), new sfn.Fail().
More in the CDK doc: https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_stepfunctions-readme.html

// Succeed state
const jobCompleted = new sfn.Succeed(stack, 'JobCompleted', {
  comment: 'Task1 job completed',
})

Step 2: Chain these task states together in a definitionBody.

// Step function definition
const definition = function1Task.next(function2Task)
  .next(otherServiceTask)
)

In the above definition, the state machine will perform function1Task, then function2Task, and lastly otherServiceTask.

Step 3: Create a StateMachine instance.

// Create a new state machine
const sm = new sfn.StateMachine(stack, 'MyStateMachine', {
  definitionBody: sfn.DefinitionBody.fromChainable(definition),
  comment: 'Run hourly until the account is deactivated or deleted',
})

Step 4: Grant the state machine necessary permissions.
In this example, you want the state machine to invoke task1LambdaFunction Lambda function:

// Grant state machine to invoke Lambda function
task1LambdaFunction.grantInvoke(sm)

Alternatively, you can use sm.addToRolePolicy() or someKindOfPolicy.attachToRole(sm.role).

#

Putting it altogether, it looks something like this:

// Step 0
import { defineBackend } from '@aws-amplify/backend'
import { Stack } from 'aws-cdk-lib'
import * as sfn from 'aws-cdk-lib/aws-stepfunctions'
import * as tasks from 'aws-cdk-lib/aws-stepfunctions-tasks'

import { task1Function } from './functions/task1/resource'
import { task2Function } from './functions/task2/resource'

export const backend = defineBackend({
  task1Function,
  task2Function,
})

// Task1 lambda function
const task1LambdaFunction = backend.task1Function.resources
  .lambda as lambda.Function

// Task2 lambda function
const task2LambdaFunction = backend.task2Function.resources
  .lambda as lambda.Function

// Look up the first stack scope
const stack = Stack.of(task1LambdaFunction)

/**
 * ******************************************
 * * Step 1: Create Task state(s)
 * ******************************************
 */
// Create a task to invoke task1LambdaFunction
const function1Task = new tasks.LambdaInvoke(stack, 'Function1', {
  lambdaFunction: task1LambdaFunction,
  outputPath: '$.Payload.body',
})

// Create a task to invoke task2LambdaFunction
const function2Task = new tasks.LambdaInvoke(stack, 'Function2', {
  lambdaFunction: task2LambdaFunction,
  outputPath: '$.Payload.body',
})

/**
 * ******************************************
 * * Step2: Create the state machine definition
 * ******************************************
 */
const definition = function1Task.next(function2Task)
  .next(otherServiceTask) // <-- Don't include this line. For illustration purposes only.

/**
 * ******************************************
 * * Step 3: Create the state machine
 * ******************************************
 */
const sm = new sfn.StateMachine(stack, 'MyStateMachine', {
  definitionBody: sfn.DefinitionBody.fromChainable(definition),
  comment: 'Run hourly until the account is deactivated or deleted',
})
#
/**
 * ******************************************
 * * Step 4: Grant state machine necessary permissions
 * ******************************************
 */
// Grant state machine to invoke Lambda function(s)
task1LambdaFunction.grantInvoke(sm)
task2LambdaFunction.grantInvoke(sm)

That should be it! Hope this helps.

wheat shale
#

hey as Mithun pointed you would need to create a custom resource for the stepFunction. The code should be similar to the sample but would need to be adjusted according to your use case. you should be able to created the functions using the defineFunction and refer them in the stepFunction states which already supports creating schedules on the function with a eventbridge
https://docs.amplify.aws/nextjs/build-a-backend/functions/scheduling-functions/

rugged crowBOT
#

✅ - Are there any examples of adding step functions in Amplify Gen2?

rugged crowBOT
amber jewel
#

@zinc quartz
I followed the suggestions posted by Sir @chrome cipher , please mark that as answer
@chrome cipher
Thank you so much.

amber jewel
#

Have a follow up question, not entirely related to Amplify, but asking for any feedback.

Use case: Run step function for all active users every hour. Step-functions will be run for each user separately

Ideally, I don't want to start step-functions for all users at same time(at start of the hour) as it will cause load spike.
So, I am thinking of an approach like this:

  1. Create an Eventbridge that runs "StepfunctionScheduer" Lambda function just before start of an hour. This event bridge would be one time creation but runs forever
  2. StepfunctionScheduer lambda reads customer table and schedules "ProcessCustomer" Step-function for each customer at 5 mins interval((numCustomers%11+ 1)*5), using Eventbridge that only runs one time.

In short, Eventbridge -- calls lambda every hour --> Lambda -- schedules step-functions every 5 mins --> Step-functions --> calls other labmdas

Is this approach bad?
Any feedback will be very helpful

Also for all of this, I am planning to maintain the code in Amplify backend