Как заставить лямбду ждать обратного вызова? - PullRequest
0 голосов
/ 03 мая 2019

Я создаю лямбда-функцию AWS, которая должна регулярно создавать резервную копию API AppSync на S3 (она запускается по правилу расписания CloudWatch). Он основан на классе, который для каждого API, переданного функцией args (с использованием переменных среды), выполняет задание резервного копирования для каждого элемента API.

Если я запускаю его, используя только узел, он работает без проблем.

Однако, когда я развертываю или тестирую локально, используя безсерверную инфраструктуру (serverless deploy и serverless invoke local -f backup), выполнение останавливается на первой асинхронной инструкции в области, отличной от области функции обработчика, независимо от того, использую ли я обратный вызов, Promise.then () или асинхронный / ожидающий синтаксис.

Я рассмотрел запуск нескольких лямбда-функций для каждой части операции резервного копирования, но тогда я потерял бы общий контекст, который мне нужен, чтобы гарантировать, что каждая часть резервного копирования выполняется правильно.

В handler.js

  // for testing purposes
    // works, waits 5 seconds and execute the rest of the code
    console.log("here1");
    await new Promise(resolve => setTimeout(resolve, 5000));
    console.log("here2");
    const allBackups = apiIds.map(apiId => new Backup(apiId));
    allBackups.map(backup => backup.start());

Результат => here1
[5 секунд ожидания]
здесь2

Однако, если я вызываю функцию, которая использует асинхронный код, такой как метод start класса Backup (в необходимом файле Backup.js), происходит следующее:



async start() {
        try {
            console.log("here3");
            const data = await this.AppSync.getGraphqlApi({ apiId: this.apiId }).promise();
            console.log("here4");

Результат => here1
[5 секунд ожидания]
* 1030 здесь 2 * here3
Конец исполнения

У меня есть все необходимые роли, и в отчетах без серверов нет проблем при развертывании или вызове локально.

Вот мой serverless.yml файл:

service:  [name]

provider:
  name: aws
  runtime: nodejs8.10

functions:
  backup:
    handler: handler.backup
    environment:
     [env variables, they are parsed properly]
    timeout: 60
    event:
      schedule: [doesn't work as well, but it's not the issue here]
        name: daily-appsync-backup
        rate: cron(0 0 ** ? *)
        enabled: false
    role: [role]

Заранее спасибо за помощь!

1 Ответ

0 голосов
/ 03 мая 2019

Хорошо, так что я нашел решение, я просто сделал это:

    const allBackups = apiIds.map(apiId => new Backup(apiId));
    await Promise.all(allBackups.map(async backup => backup.start()));

Это не сработало, потому что достигло конца функции-обработчика и не заботилось о том, что ожидают другие обратные вызовы. (Я также узнал, что вы можете await async функция, а не только Обещание.)

...