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

有些话、适合烂在心里 提交于 2019-12-23 15:21:07

问题


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?


回答1:


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);
  // rest of code...
  clearTimeout(timer);
  callback(null, result);
}



回答2:


I would like to share my solution here:
Let's say I have a Lambda handler function and it's timeout limit I set is 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:

And this is just race() operator do 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 };
};

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 timeout!' }), 200);
  })

  // start them synchronously
  const res = await Promise.race([task, timeout]);
  return res;
};


来源:https://stackoverflow.com/questions/53478200/is-there-any-way-to-catch-aws-lambda-timed-out-error-in-code-level

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!