seagatewholesale.com

Enhancing User Experience with AppSync and Step Functions

Written on

Chapter 1: Introduction

In today's fast-paced digital world, users expect quick responses after submitting a form. No one wants to wait for what seems like an eternity, right? Let's delve into an event-driven strategy that utilizes AppSync and Step Functions, providing a swift and efficient experience for form submissions. This guide is structured in concise sections with useful documentation for further exploration.

Section 1.1: Setting Up the SAM Template

To kick things off, we will employ the Serverless Application Model (SAM) macro from AWS. This feature enables us to streamline the process by automating the creation of resources, including the state machine. To get started, add the following to your SAM template:

AWSTemplateFormatVersion: "2010-09-09"

Transform: AWS::Serverless-2016-10-31

Description: >

GraphQL API linked to a state machine

Parameters:

// Provide necessary parameters, such as stage for resource name prefixes

Resources:

// Ensure proper indentation for new resources

Section 1.2: Configuring the GraphQL API

At a minimum, you will need to define a name and an authentication type for your API. Reference the AWS::AppSync::GraphQLApi documentation for additional fields you may require.

GraphQLApi:

Type: AWS::AppSync::GraphQLApi

Properties:

Name: MyApi

AuthenticationType: AWS_IAM

Subsection 1.2.1: Setting Up the Schema

For clarity, I've included an inline schema definition, but you may also store it in a separate file under the DefinitionS3Location property. Your FormInput should encapsulate any relevant fields. Since this form involves data writing operations, it will utilize a mutation, specifically named submitToForm.

GraphQLApiSchema:

Type: AWS::AppSync::GraphQLSchema

Properties:

ApiId: !GetAtt GraphQLApi.ApiId

Definition: |

type FormResponse {

status: String

}

input FormInput {

id: String

otherFields: [String]

}

type Mutation {

submitToForm(input: FormInput) : FormResponse

}

schema {

mutation: Mutation

}

Section 1.3: Setting Up the State Machine

Now, let's configure the state machine. To ensure an optimal user experience, we aim for rapid responses, even during simultaneous form submissions. For this, an EXPRESS workflow is ideal. Below are examples of supported tasks within an EXPRESS workflow. You will need to establish permissions based on your specific requirements.

StateMachine:

Type: AWS::Serverless::StateMachine

Properties:

Name: sample-state-machine

Type: EXPRESS

Definition:

Comment: An example of the Amazon States Language

StartAt: Validate Form

States:

Validate Form:

Type: Task

Resource: arn:aws:states:::lambda:invoke

OutputPath: "$.Payload"

Parameters:

Payload.$: "$"

FunctionName: "${ValidateFormLambdaArn}"

Retry:

  • ErrorEquals:

    • Lambda.ServiceException
    • Lambda.AWSLambdaException
    • Lambda.SdkClientException

    IntervalSeconds: 2

    MaxAttempts: 6

    BackoffRate: 2

Next: Send an EventBridge custom event

Send an EventBridge custom event:

Type: Task

Resource: 'arn:aws:states:::events:putEvents'

Parameters:

Entries:

  • Detail:

    Message: 'Hello from Step Functions!'

    DetailType: MyDetailType

    EventBusName: MyEventBusName

    Source: MySource

Next: Save Form Data Details

Save Form Data Details:

Type: Task

Parameters:

TransactItems.$: "$.items"

Resource: arn:aws:states:::aws-sdk:dynamodb:transactWriteItems

InputPath: "$.transactWrite"

ResultPath: "$.transactWriteItemResponse"

Next: Format Return Response

Format Return Response:

Type: Pass

End: true

InputPath: "$.response"

ResultPath: "$.input"

OutputPath: "$.input"

Section 1.4: Establishing Permissions

This IAM Role is crucial as it enables AppSync to initiate synchronous executions.

ServiceRole:

Type: AWS::IAM::Role

Properties:

AssumeRolePolicyDocument:

Version: "2012-10-17"

Statement:

  • Effect: "Allow"

    Principal:

    Service: "appsync.amazonaws.com"

    Action: "sts:AssumeRole"

Path: "/"

Policies:

  • PolicyName: "dev-start-sync-execution"

    PolicyDocument:

    Version: "2012-10-17"

    Statement:

    • Effect: "Allow"

      Action: "states:StartSyncExecution"

      Resource: !Ref StateMachine

Chapter 2: Configuring the Data Source and Resolver

Section 2.1: Defining the Data Source

A data source represents the AWS component that your GraphQL API will interact with, in this case, a step function. It's essential for it to be able to assume the service role. The HTTP configuration should point to the AWS endpoint for synchronous states.

StepFunctionHTTPDataSource:

Type: AWS::AppSync::DataSource

Properties:

ApiId: !GetAtt GraphQLApi.ApiId

Type: HTTP

ServiceRoleArn: !GetAtt ServiceRole.Arn

HttpConfig:

AuthorizationConfig:

AuthorizationType: AWS_IAM

AwsIamConfig:

SigningRegion: !Ref AWS::Region

SigningServiceName: states

Section 2.2: Configuring the Resolver

This is where everything converges! As previously mentioned, we utilize a mutation. The ApiId corresponds to the configured API, and FieldName is submitToForm, as defined in our schema. The data source is linked to the synchronous states execution endpoint, which has the appropriate service role.

AppSyncMutationToStepFunction:

Type: AWS::AppSync::Resolver

Properties:

ApiId: !GetAtt GraphQLApi.ApiId

TypeName: Mutation

FieldName: submitToForm

DataSourceName: !Ref StepFunctionHTTPDataSource.Name

RequestMappingTemplate: !Sub >

{

#set( $input = $ctx.arguments.input )

"version": "2018-05-29",

"method": "POST",

"resourcePath": "/",

"params": {

"headers": {

"content-type": "application/x-amz-json-1.0",

"x-amz-target": "AWSStepFunctions.StartSyncExecution"

},

"body": {

"stateMachineArn": "${StateMachine}",

"input": "$util.escapeJavaScript($util.toJson($input))"

}

}

}

ResponseMappingTemplate: >

#if($context.error)

$util.error($context.error.message, $context.error.type)

#else

#set( $body = $util.parseJson($context.result.body) )

$body.output

#end

Wrapping Up

A significant aspect of event-driven development is the separation of logic. By employing a step function to manage form submissions and dispatch events throughout the workflow, we enhance efficiency. The EXPRESS type is particularly beneficial for handling numerous requests, ensuring they take less than five minutes to complete.

I am not providing specific ASL JSON since your exact requirements may vary, but the best practice is to emit an event based on the input data. You also have various commands available, such as writing items to DynamoDB or executing a Lambda function. The key is to ensure that all steps remain within the five-minute threshold for optimal speed.

Ultimately, users are indifferent to what occurs behind the scenes; they simply need assurance that their form submission was successful and they received a confirmation. With an event-driven approach, we can efficiently manage processing while maintaining quick response times.

The video titled "AWS Serverless Project: Contact Form Application using Lambda, S3, DynamoDB, API Gateway & Cognito" demonstrates the practical implementation of these concepts, providing a visual guide to enhance understanding.

Share the page:

Twitter Facebook Reddit LinkIn

-----------------------

Recent Post:

Desalination: Analyzing Costs and Potential Solutions

Exploring the costs and challenges of desalination, while considering its potential as a solution to water shortages.

Innovating Quantum Futures: The Journey of Whurley and Strangeworks

Explore the visionary journey of William Hurley, aka Whurley, and his contributions to the world of quantum computing through Strangeworks.

Cybersecurity Threats: Unveiling the First Fileless Malware Incident

A groundbreaking discovery of fileless malware by Kaspersky Lab reveals new vulnerabilities in Windows operating systems.