I am testing out aws lambda, using nodejs with the 4.3 version. I\'m able to successfully complete all the statements in my handler function within the console test, which i
If anybody was confused like I was with how to add callbackWaitsForEmptyEventLoop
to new Alexa projects that look like this:
const skillBuilder = Alexa.SkillBuilders.custom();
exports.handler = skillBuilder
.addRequestHandlers(
GetNewFactHandler,
HelpHandler,
ExitHandler,
FallbackHandler,
SessionEndedRequestHandler,
)
.addRequestInterceptors(LocalizationInterceptor)
.addErrorHandlers(ErrorHandler)
.lambda();
Example project found here: https://github.com/alexa/skill-sample-nodejs-fact/blob/master/lambda/custom/index.js
This solution worked for me:
// create a custom skill builder
const skillBuilder = Alexa.SkillBuilders.custom();
exports.handler = (event, context, callback) => {
// we need this so that async stuff will work better
context.callbackWaitsForEmptyEventLoop = false
// set up the skill with the new context
return skillBuilder
.addRequestHandlers(
GetNewFactHandler,
HelpHandler,
ExitHandler,
FallbackHandler,
SessionEndedRequestHandler,
)
.addRequestInterceptors(LocalizationInterceptor)
.addErrorHandlers(ErrorHandler)
.lambda()(event, context, callback);
}
I was triggering a lambda from android code. The lambda was performing a heavy data lifting operation from DynamoDB and generating a JS object as a response. I could see the generated object in my lambda logs, but my android side code always timed out waiting for a response.
The reason for timeout was the Invocation payload (request and response) limit of 6 MB for synchronous and 256 KB for asynchronous lambda implementation. In my case I had a asynchronous implementation and the resultant object was over 256 KB.
There was no appropriate log message for overshooting this limit which derailed me. Reference: https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-limits.html
The workaround I implemented was writing the response to a text file in S3 bucket and passing its reference as a response to the android side instead of passing the actual object itself.
You have a typo:
context.callbackWaitsForEmtpyEventLoop = false;
should be:
context.callbackWaitsForEmptyEventLoop = false;
Here's what the documentation says about the behavior of callbackWaitsForEmptyEventLoop:
callbackWaitsForEmptyEventLoop
The default value is
true
. This property is useful only to modify the default behavior of the callback. By default, the callback will wait until the Node.js runtime event loop is empty before freezing the process and returning the results to the caller. You can set this property to false to request AWS Lambda to freeze the process soon after the callback is called, even if there are events in the event loop. AWS Lambda will freeze the process, any state data and the events in the Node.js event loop (any remaining events in the event loop processed when the Lambda function is called next and if AWS Lambda chooses to use the frozen process). For more information about callback, see Using the Callback Parameter.
Minimal example:
// Times out due to typo
exports.function1 = (event, context, callback) => {
setInterval(() => console.log('Long wait'), 100000);
context.callbackWaitsForEmtpyEventLoop = false;
callback(null, 'Hello from Lambda');
};
// Returns successfully
exports.function2 = (event, context, callback) => {
setInterval(() => console.log('Long wait'), 100000);
context.callbackWaitsForEmptyEventLoop = false;
callback(null, 'Hello from Lambda');
};