Is it the strongest or easy?
Common as a serverless configuration API Gateway & Lambda
** API Gateway has a 29 second limit **, ** Lambda has a 15 minute limit **
While making full use of Lambda's performance To fill that gap ** I want to make an asynchronous API with as simple a configuration as possible ** I think there is.
What you need at that time
--API for kicking Lambda --API to determine if the kicked Lambda is complete and receive a response
I think it is, but the Step Functions below have both **
Step Functions
In Step Functions Make workflows visually and handsome, such as linking microservices Can be configured.
** Official example: **

https://aws.amazon.com/jp/blogs/news/new-aws-step-functions-build-distributed-applications-using-visual-workflows/
It's dangerous I think I can do anything
By defining Lambda as a Task You can incorporate it into this workflow.
By the way, this is the one I will make this time (cute)


I will make it like this
APIfor start-execution to kick the aboveLambda  API for describe-execution to receive response from Lambda
(The name can be anything)
** Both are POST **
Serverless Framework
https://github.com/ChaseSan/async-api-sample
I will actually make it with SLS
It's much easier than making it with CFn,
You need to include serverless-step-functions as a plugin
serverless.yml
plugins:
  - serverless-step-functions
The function is created like this ** Ramen timer **
serverless.yml
functions:
  async-api:
    handler: app.lambda_handler
    name: async-api-${self:provider.stage}
    environment:
      TIMER: 30
app.py
import os
from time import sleep
import logging
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
def lambda_handler(event, context):
    logger.info(f"event: {event}")
    seconds = int(os.environ.get("TIMER"))
    sleep(seconds)
    return {"message": "The ramen is boiled. If you don't eat it quickly, it will grow."}
The definition of Step Functions looks like this
When using the serverless-step-functions plugin
Also write the API Gateway definition inside the stateMachines block
serverless.yml
stepFunctions:
  stateMachines:
    state-machine:
      name: state-machine-${self:provider.stage}
      events:
        - http:
            path: ${self:custom.basePath}/start-execution
            method: post
            action: StartExecution
            iamRole:
              Fn::GetAtt: [AsyncApiRole, Arn]
            request:
              template:
                application/json: |-
                  {
                    "stateMachineArn":"arn:aws:states:#{AWS::Region}:#{AWS::AccountId}:stateMachine:state-machine-${self:provider.stage}"
                  }
        - http:
            path: ${self:custom.basePath}/describe-execution
            method: post
            action: DescribeExecution
            iamRole:
              Fn::GetAtt: [AsyncApiRole, Arn]
            response:
              template:
                application/json: |-
                  {
                    "input": $util.parseJson($input.json('$.input')),
                    #if($input.path('$.output') != "")
                      "output": $util.parseJson($input.json('$.output')),
                    #end
                    "status": $input.json('$.status')
                  }
      definition:
        StartAt: async-api-task
        States:
          async-api-task:
            Type: Task
            Resource:
              Fn::GetAtt: [async-api, Arn]
            End: true
** Points **
--In start-execution, describe StartExecution in ʻevents.http.action.  --ʻEvents.http.request.template describes Arn of StateMachine to be executed in Json format.
--In describe-execution, describe DescribeExecution in ʻevents.http.action.  --Description the response in Json format in ʻevents.http.request.template
{
    "response": $input.json('$'),
}
Anyway, all the contents of DescribeExecution will be returned. It would be better to return only what you need in terms of interface (probably)
Let's deploy and move
sls deploy
 Try it with the endpoint that appears in the console
Try it with the endpoint that appears in the console
start-execution
 Use the obtained ʻexecutionArn` to hit the following API
Use the obtained ʻexecutionArn` to hit the following API
describe-execution

Something has returned.
status is RUNNING.
It seems that ramen hasn't been made yet.
Let's hit it again after a while

Oh, status became SUCCEEDED, and you told me that the ramen was completed.
No, it ’s really easy. Without this, I would have to make full use of Dynamo and SQS and implement it myself (hell).
Recommended Posts