Monday, October 15, 2018

AWS Lambdas.. use context or callback to respond to the caller?


AWS Lambdas are great. No need to run your own servers and all that, simply awesome. However working with Lambdas introduces Lambda specific problems and responding to the caller is one of those things you just need to get familiar with if you need to do anything more than "hello world".

Ok, so when AWS Lambda is invoked it's handler will be executed. With runtime version before 4.3.2 the way to respond to caller was by using context.succeed(), context.fail() or context.done() e.g.:

exports.handler = function(event, context) {
    // something here
    context.succeed();
}

This context call was resulting in lambda being "frozen" at this very point, even if Node's event loop was not empty. This could be the case when some asynchronous operation wasn't finished, connection to database was not closed etc. Now, as this lambda invocation was not finished and so new lambda invocation might (not necessarily though) use the same container, the result of leftovers in event loop might apparently be quite unpredictable.

With version 4.3.2 third parameter to handler function was introduced and so handler might look something as below:

exports.handler = function(event, context, callback) {
    // something here
}

This new callback parameter is an improvement on previous context.succeed(), context.fail() and context.done(). It takes err or success parameters and more on callback(err, success) itself you can find in AWS docs.

Unlike calling context.succeed/fail/done, calling callback(..) will not immediately freeze lambda execution, but rather wait till the event loop is empty. It solves an issue with non-empty event loop when lambda being frozen, however it also results in confusing behaviour as many expects lambda to immediately finish and this is not the case.

To cater for this behavior callbackWaitsForEmptyEventLoop property was made available on context object. Setting it to false e.g.:

exports.handler = function(event, context, callback) {
    context.callbackWaitsForEmptyEventLoop = false;
}

will result in Lambda execution freezing immediately on callback(..) call and leaving content of event loop as it is.

Even though I'm aware of the risk, I found this usefull when connecting to database and it helped me to reuse connection pool and avoid closing opening database connections with every lambda invocation.

No comments:

Post a Comment