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 includes connecting to a mongodb host within our vpc. But, the function always times out. I've found several posts and resources that discuss using the callback, and setting properties on the context, and IAM role permissions, but no matter what I do, it always ends up timing out. Current code:
'use strict'; var Mongoose = require('mongoose'); var Device = require('./device_model'); var Alarm = require('./alarm_model'); var Event = require('./event_model'); var mongoConnection = process.env.MONGO_URL; var connection = Mongoose.connect(mongoConnection); Mongoose.connection.once('open', function() { console.log("Connecting to mongo at: " + mongoConnection); console.log("Mongoose connection in lambda opened"); }); Mongoose.connection.on('error', function(){ console.error("Error creating mongoose connection in lambda, exiting!"); process.exit(1); }); exports.check_alarms = function(event, context, callback) { context.callbackWaitsForEmtpyEventLoop = false; console.log("The incoming event: " + JSON.stringify(event)); var device = null; Device.findByUUID(event.uuid, function(error, result){ if(!error){ device = result; console.log("the device: " + JSON.stringify(device)); if(event.Ale && event.Ale.length > 0) { console.log("We have an alarm, checking if already set"); callback(null, {"status":"alarms"}); } else { console.log("Event contains no alarm; checking for historic active"); callback(null, {"status":"no alarms"}); } } else { console.log("there's a problem on mongo"); callback("problem", "status not so good"); } }); callback(null, {"status":"outside of device find block"}); }
Finding the root cause of the timeout. There are many reasons why a function might time out, but the most likely is that it was waiting on an IO operation to complete.
You can now configure your AWS Lambda functions to run up to 15 minutes per execution. Previously, the maximum execution time (timeout) for a Lambda function was 5 minutes.
To solve the "Task timed out after X seconds" error in AWS lambda, you have to: 1 Increase the function's timeout. The default value is 3 seconds , the maximum is 15 minutes. 2 Increase the function's memory. By default it's set to 128 Mb which is way too low and ads onto the function's execution... More ...
AWS intentionally stopped a function invocation once it hit a run-time of X seconds. What does this mean? Lambda functions are limited to a maximum execution time of 15 minutes. A custom limit can be configured when the Lambda function is created.
The function has a timeout of 15 minutes, so the thread will be kept waiting for the response. However, the threshold limit for API Gateway is 29 seconds, so the user will receive the AWS Lambda timeout error after 29 seconds. Not only is this a poor experience for the user but it will also result in additional cost.
The limit is in place because Lambda functions are meant to be small and quick rather than large applications. How do I fix if Lambda task is timed out? Enable AWS X-ray tracing to get a breakdown of the execution.
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'); };
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); }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With