7
votes

Docs says:

By default, the Invoke API assumes RequestResponse invocation type. You can optionally request asynchronous execution by specifying Event as the InvocationType.

So all I can send to my function (python) is InvocationType:Event everywhere:

curl -X POST "https://X.execute-api.us-east-1.amazonaws.com/prod/Y?InvocationType=Event" 
-d "InvocationType:Event" 
-H "X-Amz-Invocation-Type:Event"

(function sleeps 3 seconds then responses)

null

But is not Async... docs also says:

When you invoke a Lambda function via the AWS console or over HTTPS using Amazon API Gateway, Lambda always uses the RequestResponse invocation type.

I know that can be possible via aws-CLI, what I dont understand if it is possible to do it from API Gateway endpoint.

4

4 Answers

12
votes

Create two Lambdas and in the first use Lambda.Client.invoke with InvocationType=Event in an dedicated ApiGateway request handling Lambda. The second executes the logic you want the ApiGateway request to asynchronously invoke.

Example dedicated ApiGateway Lambda handler:

from __future__ import print_function

import boto3
import json

def lambda_handler(event, context):
    response = client.invoke(
        FunctionName='<your_long_task_running_function_executer>',
        InvocationType='Event',
        Payload=json.dumps(event)
    )
    return { "result": "OK" }

You would likely want to detect a failure to send the request and other conditions of that sort but as I don't primarily use python, I'll leave that logic up to you.

p.s. note that invoke_async is deprecated
p.p.s. sorry, my account is new and I don't have the rep to add these as a comment: 0. I borrowed from what you answered; 1. you are using a deprecated api; and 2. you ought (clearly it's been fine) to add InvocationType = 'Event' into your call.

1
votes

I realized that API Gateway only call lambda functions with RequestResponse by design.

But you can do it writing 2 functions:

  1. A "Function Receiver" that invokes the async call to a "Function Executer"

    from __future__ import print_function
    
    import boto3
    import json
    
    def lambda_handler(event, context):
        client = boto3.client('lambda')
        client.invoke_async(
            FunctionName='my_long_task_running_function_executer',
            InvokeArgs=json.dumps(event)
        )
        return {"result": "OK"}
    
  1. A "Function Executer" that executes the long running task.

Then you will have a process that you can start with an API Gateway and execute it as InvocationType=Event.

0
votes

I know why you want to do this, but it isn't the right solution.

Whatever you do, don't use two lambda functions.

You can't control how lambda is being called, async or sync. The caller of the lambda decides that. For APIGW, it decides call lambda sync.

The possible solutions are one of:

  • SQS
  • Step Functions (SF)
  • SNS

In your API, you call out to one of these services, get back a success, and then immediately return a 202 to your caller.

If you have a high volume of single or double action execution use SQS. If you have potentially long running with complex state logic use SF. If you for someone reason want to ignore my suggestions, use SNS.

Each of these can (and should) call back out to a lambda. In the case that you need to run more than 15 minutes, they can call back out to CodeBuild. Ignore the name of the service, it's just a lambda that supports up to 8 hour runs.


Now, why not use two lambdas (L1, L2)? The answer is simple. Once you respond that your async call was queued (SQS, SF, SNS), to your users (202). They'll expect that it works 100%. But what happens if that L2 lambda fails. It won't retry, it won't continue, and you may never know about it.

That L2 lambda's handler no longer exist, so you don't know the state any more. Further, you could try to add logging to L2 with wrapper try/catch but so many other types of failures could happen. Even if you have that, is CloudWatch down, will you get the log? Possible not, it just isn't a reliable strategy. Sure if you are doing something you don't care about, you can build this arch, but this isn't how real production solutions are built. You want a reliable process. You want to trust that the baton was successfully passed to another service which take care of completing the user's transaction. This is why you want to use one of the three services: SQS, SF, SNS.