Reputation: 51
I'm trying to build out an architecture in Serverless Framework where one Lambda calls another Lambda asynchronously, using the Node.js AWS SDK. I understand that when invoking asynchronously, the calling Lambda will not wait for the called Lambda to run and respond, but instead will get a response from AWS with the status of the invocation itself.
From what I've read, the way to call a Lambda asynchronously is to use the Lambda invoke()
method with InvocationType: 'Event'
in the params (as opposed to synchronous invocation with InvocationType: 'RequestResponse'
). However, it doesn't seem to matter what I set as the InvocationType
; the second Lambda always runs in full and returns its response to the first, just as if I had set InvocationType: 'RequestResponse'
.
In my serverless.yml
file, I have:
functions:
receive_deltas:
handler: src/record/delta_lambdas.receive
vpc: ${self:custom.vpc}
events:
- http:
method: post
path: v1/deltas
process_deltas:
handler: src/record/delta_lambdas.process
vpc: ${self:custom.vpc}
In my TypeScript handler, I have:
import { Lambda } from 'aws-sdk';
export const receive = async (event) => {
const { recordIds } = JSON.parse(event.body);
const lambda = new Lambda({
region: 'us-west-2',
endpoint: 'http://localhost:3003',
});
const params = {
FunctionName: 'orgconfig-dev-process_deltas',
InvocationType: 'Event',
Payload: JSON.stringify({ recordIds }),
};
lambda.invoke(params, (err, data) => {
if (err) {
console.log(err);
return failureResponse(err);
} else {
return parseResponse(data);
}
});
};
export const process = async (event) => {
console.log('running process lambda');
// process a bunch of stuff
console.log('finished processing');
};
The first Lambda always waits for the second Lambda to run in its entirety, and eventually gets a response of { StatusCode: 200, Payload: '' }
. I'm expecting a successful async invocation to return an immediate response with StatusCode: 202
.
What am I missing?
Upvotes: 3
Views: 2888
Reputation: 106
a configuration that's worked for them with Serverless Offline and async Lambda invocation, it might be worth posting here for future internauts
Just in case someone's looking for a working config ...
Try async: true for both (invoker and invoked) functions in serverless.yml
InvocationType should be "Event" in lambda.invoke parameters
iam role statements : lambda:InvokeAsync
FunctionName for offline invocation should come in the format serviceName-stage-functionName, so all together it looks like:
functions:
invoker:
handler: ...your-handler
environment:
your_Ref_to_offlineLamName: "${self:service}-${opt:stage, self:provider.stage}-invoked"
events:
- http:
method: get
path: ...yourpath
async: true
invoked:
handler: ...somehandler
events:
- http:
method: post
path: ...somepath
async: true
handler
let param = {
FunctionName: process.env.IS_OFFLINE == "true" ? process.env.your_Ref_to_offlineLamName : "whatever",
InvocationType: "Event",
Payload: JSON.stringify({test:"TESTTEST"})
};
lambda.invoke(param).promise()
tested in node15. (based on https://www.serverless.com/plugins/serverless-offline#usage-with-invoke)
Upvotes: 0
Reputation: 51
What I was missing, it seems, was that the Serverless Offline plugin—or at least my configuration of it—does not emulate asynchronous lambda invocation in this way. (Note in my Lambda constructor I had a localhost endpoint giving away that it was offline.) Once I deployed to an AWS instance, it worked perfectly.
If anyone has a configuration that's worked for them with Serverless Offline and async Lambda invocation, it might be worth posting here for future internauts.
Upvotes: 2