Reputation: 121
I am using AWS SAM with Python. My goal is to have two Lambdas:
There are a couple other SO questions which deal with this scenario, but as far as I can tell none have touched on how to do it when deploying SAM locally.
Here is my SAM template file:
# template.yaml
Resources:
FunctionA:
# PUT /functions/a, should invoke FunctionB asynchronously
Type: AWS::Serverless::Function
Properties:
CodeUri: api/
Handler: functions.a
Runtime: python3.7
Events:
FunctionA:
Type: Api
Properties:
Path: /functions/a
Method: put
FunctionB:
# Long-running asynchronous function
Type: AWS::Serverless::Function
Properties:
FunctionName: 'FunctionB'
CodeUri: api/
Handler: functions.b
Runtime: python3.7
EventInvokeConfig:
MaximumRetryAttempts: 2
DestinationConfig:
OnSuccess:
Type: SQS
OnFailure:
Type: SQS
And my Python lambda handler logic:
# functions.py
def a(event, context):
boto3.client('lambda').invoke(
FunctionName='FunctionB',
InvocationType='Event',
Payload='some_data'.encode('UTF-8')
)
return { "statusCode": 200, "body": {} }
def b(data):
print("SUCCESS!")
I deploy it locally:
# deploy.sh
sam build
sam local start-api
All is well until this point. When I call PUT /functions/a
, I get the following error indicating that Function B could not be invoked from Function A:
[ERROR] ResourceNotFoundException: An error occurred (ResourceNotFoundException) when calling the Invoke operation: Function not found: arn:aws:lambda:us-east-2:[iam-user-id]:function:FunctionB
Has anyone found a fix for this? Here's what I've tried:
sam local invoke FunctionB # works great
InvocationType=Event
to InvocationType=RequestResponse
and received the same errorboto3.client('lambda', endpoint_url='http://localhost:3000')
# [ERROR] EndpointConnectionError: Could not connect to the endpoint URL: "http://localhost:3000/2015-03-31/functions/ScheduleShowsAsyncFunction/invocations"
Upvotes: 12
Views: 6507
Reputation: 462
You can use sam local start-lambda to run FunctionA, it will emulates on port 3001, and call it from FunctionB with lambda client:
boto3.client('lambda', endpoint_url='http://docker.for.mac.localhost:3001')
You have to use InvocationType=RequestResponse
because Event is not yet supported https://github.com/awslabs/aws-sam-cli/pull/749
If FunctionB is long-running and because you can only use RequestResponse you can change lambda client config to increase timeout:
config_lambda = Config(retries={'total_max_attempts': 1}, read_timeout=1200)
lambda_client = boto3.client('lambda',
config=config_lambda,
endpoint_url='http://docker.for.mac.localhost:3001')
Upvotes: 6