Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any way to catch AWS lambda timed out error in code level?

Tags:

Is there any way to catch AWS lambda timed out error in code-level so that I can have a chance to handle for the error before exiting the lambda function?

like image 833
SangminKim Avatar asked Nov 26 '18 09:11

SangminKim


People also ask

What happens if Lambda timeout?

You can now set the timeout value for a function to any value up to 15 minutes. When the specified timeout is reached, Amazon Lambda terminates execution of your Lambda function.

How do I find my AWS Lambda error?

To troubleshoot Lambda code errors You can use CloudWatch to view all logs generated by your function's code and identify potential issues. For more information, see Accessing Amazon CloudWatch Logs for AWS Lambda.

What is the most likely issue with the Lambda function timeout?

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.


2 Answers

While the lambda environment doesn't fire a "timing out" event, you can do this yourself fairly trivially.

Each language has a function exposed by the context object to get the remaining time in milliseconds.

You can use that, in tandem with the timer functionality of whatever language you're using to ensure you get notified before timeout.

For example (node):

function handler(event, context, callback) {   const timer = setTimeout(() => {     console.log("oh no i'm going to timeout in 3 seconds!");     // &c.   }, context.getRemainingTimeInMillis() - 3 * 1000);   try {     // rest of code...   } finally {     clearTimeout(timer);   }   callback(null, result); } 
like image 169
thomasmichaelwallace Avatar answered Sep 19 '22 09:09

thomasmichaelwallace


Update:

Use the built-in Promise.race() function instead:

 module.exports.myFunction = async (event) => {    // your real task   const task = new Promise((resolve) => {     setTimeout(() => resolve({ statusCode: 200, message: 'Task finished.' }), 1000);   })    // add a new "task": timeout    const timeout = new Promise((resolve) => {     setTimeout(() => resolve({ statusCode: 504, message: 'Sorry, your task timed out!' }), 200);   })      // start them synchronously   const res = await Promise.race([task, timeout]);   return res; }; 

I would like to share my solution here:
Let's say I have a Lambda handler function and it's timeout limit I set was 15 mins. Inside this function, I have an async function named work() which may takes longer that 15 mins.

To catch the timeout error from Lambda, my way is:
I create a new async function named timeout(), and this function simply return after 14.9 mins. And I let work() and timeout() functions start at the same time, if work() can finish in 14.9 mins, then work() returns earlier that timeout(), otherwise, timeout() returns earlier.
You can see it easier with this diagram:

enter image description here

And this is just what race() operator does from rxjs.

Here is the code that implement this idea by using rxjs:

module.exports.myFunction = async (event) => {   function task() {     return new Promise((resolve, reject) => {       setTimeout(() => {         resolve('finished!');       }, 15 * 60 * 1000);     });   }    function timeout() {     return new Promise((resolve, reject) => {       setTimeout(() => {         resolve('timeout!');       }, 14.9 * 60 * 1000);     });   }     const res = await new Promise((resolve, reject) => {     race(from(task()), from(timeout()))       .subscribe(msg => {         resolve(msg);       })   });    return { res }; }; 
like image 37
backslash112 Avatar answered Sep 17 '22 09:09

backslash112