invokeFunction = async (handlerFunction, { event, partialContext }) => {
  return new Promise(async (resolve, reject) => {
    const callback = (error, response) => {
      if (error) {
        reject(error)
      } else {
        resolve(response)
      }
    }

    const startTime = new Date()

    const context = {
      ...partialContext,
      succeed(result) {
        callback(null, result)
      },
      fail(error) {
        callback(error, null)
      },
      done(error, result) {
        callback(error, result)
      },
      getRemainingTimeInMillis() {
        return Math.max(
          context.timeout * 1000 - (new Date().valueOf() - startTime.valueOf()),
          0,
        )
      },
    }

    try {
      const response = await handlerFunction(event, context, callback)
      resolve(response)
    } catch (error) {
      reject(error)
    }
  })
}
Invoke the handler function with the event, context and callback.
We add context functions to the context object we received via WebSockets.

@param {*} handlerFunction The handler function to invoke
@param {{ event: any, partialContext: any }} options
@returns <Promise<any>} a promise that resolves with the response from the handler function
@throws {Error} if the handler function is not a function, or if the handler function throws an error