diff --git a/src/errors/LambdaTimeoutError.js b/src/errors/LambdaTimeoutError.js new file mode 100644 index 000000000..ac6dc7a89 --- /dev/null +++ b/src/errors/LambdaTimeoutError.js @@ -0,0 +1 @@ +export default class LambdaTimeoutError extends Error {} diff --git a/src/errors/index.js b/src/errors/index.js new file mode 100644 index 000000000..4f3387a06 --- /dev/null +++ b/src/errors/index.js @@ -0,0 +1,2 @@ +// eslint-disable-next-line import/prefer-default-export +export { default as LambdaTimeoutError } from './LambdaTimeoutError.js' diff --git a/src/lambda/LambdaFunction.js b/src/lambda/LambdaFunction.js index 773bb831f..242cd645a 100644 --- a/src/lambda/LambdaFunction.js +++ b/src/lambda/LambdaFunction.js @@ -14,6 +14,7 @@ import { DEFAULT_LAMBDA_TIMEOUT, supportedRuntimes, } from '../config/index.js' +import { LambdaTimeoutError } from '../errors/index.js' import { createUniqueId } from '../utils/index.js' const { ceil } = Math @@ -40,8 +41,6 @@ export default class LambdaFunction { #handler = null - #handlerRunDone = false - #handlerRunner = null #idleTimeStarted = null @@ -281,14 +280,7 @@ export default class LambdaFunction { async #timeoutAndTerminate() { await setTimeoutPromise(this.#timeout) - // if the handler has finished before the timeout don't terminate - if (this.#handlerRunDone) { - return - } - - await this.#handlerRunner.cleanup() - - throw new Error('Lambda timeout.') + throw new LambdaTimeoutError('Lambda timeout.') } async runHandler() { @@ -307,14 +299,20 @@ export default class LambdaFunction { this.#startExecutionTimer() - this.#handlerRunDone = false + let result - const result = await Promise.race([ - this.#handlerRunner.run(this.#event, context), - ...(this.#noTimeout ? [] : [this.#timeoutAndTerminate()]), - ]) + try { + result = await Promise.race([ + this.#handlerRunner.run(this.#event, context), + ...(this.#noTimeout ? [] : [this.#timeoutAndTerminate()]), + ]) + } catch (err) { + if (err instanceof LambdaTimeoutError) { + await this.#handlerRunner.cleanup() + } - this.#handlerRunDone = true + throw err + } this.#stopExecutionTimer() @@ -330,6 +328,7 @@ export default class LambdaFunction { } this.#status = 'IDLE' + this.#startIdleTimer() return result