Предложите подход к обработке нескольких лямбда-вызовов

Главная проблема: Функция Lambda не завершается после успешного вызова внешнего API, что впоследствии вызывает несколько внешних вызовов API.

У меня есть лямбда-функция, которая прослушивает слабые события, когда происходит событие, когда вызывается лямбда-функция. Я фильтрую эти события, используя некоторые проверки условий, и когда происходит целевое событие, я делаю внешний вызов API.

Все вышеперечисленное работает, однако внешний вызов API запускается несколько раз для одного события (~ 4 раза, когда он должен быть 1 в случае успеха).

Идемпотент - Часто люди связывают эту проблему с идемпотентностью, однако, учитывая внешний вызов API в блоке условий, который запускается несколько раз, я не считаю это проблемой.

  • Я могу подтвердить, что проверка условий правильно фильтрует соответствующие события
  • Я могу подтвердить, что получаю statusCode 200 перед последующими (дополнительными) внешними вызовами API
  • Я включил context.done() и лишние callback(), но не повезло

Поиск некоторых предлагаемых подходов

  • У кого-нибудь есть предложенный подход к устранению этой проблемы?
  • Я читал, что некоторые люди используют DynamoDB для отслеживания запросов на выполнение, но это не похоже на отличный подход.

Я прикрепил лямбда-функцию ниже:

const axios = require('axios');

const sendMessages = async(event, context, callback) => {
    // test the message for a match
    if (event.type === 'message' && event.bot_id !== undefined) {
        console.info("filter events for specific event");

        let URL = 'https://someurl.com/slack/events';
        let response = await axios.post(URL, {
            events: event,
        });
        console.info("response success :: ", response.status);
        if (response.status === 200) {
            console.info("condition met");
            context.done();
            callback(null, 'successful request');
        }
    }
    callback(null, 'successful request');
};

// Lambda handler
exports.server = (data, context, callback) => {
    let eventData = JSON.parse(data.body);
    switch (data.path) {
        case "/slack-events": sendMessages(eventData.event, context, callback); break;
        default: callback(null);
    }
};

Ожидаемое поведение

  • Сделать один вызов внешнего API при вызове и проверке условия; выйти после response.status === 200

@JohnRotenstein, не могли бы вы связаться с командой документации и узнать, могут ли они обновить документы? Однажды я связался с @SebastienStomarq, и он сказал, что уже разговаривал с командой документации, но до сих пор документы не были обновлены. Большинство вопросов, на которые мы получаем ответы на SO в эти дни, касаются async/await, используемого в сочетании с вызовами context и callback, что создает абсолютный беспорядок. Эти вопросы будут продолжать поступать, если документы не будут исправлены.

Thales Minussi 18.07.2019 11:50

@ThalesMinussi Вы можете нажать кнопку «Отзыв» на страницах документации, которые будут перенаправлены группам документации. Однако, если вы хотите написать более подробное объяснение, не стесняйтесь отправить его мне по электронной почте, и я подниму его вместе с командой документации. (Я не специалист по Node, поэтому было бы хорошо, если бы кто-то, знакомый с большинством проблем, задокументировал для них проблему.)

John Rotenstein 18.07.2019 11:55

@JohnRotenstein Идеально. Я сделаю это, когда у меня будет свободное время, чтобы написать подробное объяснение. Спасибо, что нашли время, чтобы вернуться ко мне. Может быть, открыть исходный код документов было бы хорошей идеей...

Thales Minussi 18.07.2019 11:59

@ThalesMinussi Документация AWS доступна на github, поэтому вы можете отправлять запросы на включение (но я не уверен, что там есть руководства по ВСЕ).

John Rotenstein 18.07.2019 12:01

@JohnRotenstein github.com/awsdocs/aws-doc-sdk-examples/issues/754 Я уже сделал PR. Посмотрим, как вы, ребята из AWS, и сообщество отреагируете.

Thales Minussi 18.07.2019 13:55
Доступ AWS Java Lambda к экземпляру AWS RDS MySQL с помощью CDK
Доступ AWS Java Lambda к экземпляру AWS RDS MySQL с помощью CDK
В этой статье мы рассмотрим, как включить доступ Java Lambda к экземпляру AWS RDS MySQL.
1
5
137
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблема (вы не первый и не последний, кто задает этот тип вопроса, AWS необходимо исправить документы как можно скорее) заключается в том, что вы смешиваете async/await с вызовами context.done и callback().

Если ваши функции уже async, то придерживайтесь await до конца и забудьте о context и callback объектах.

Обратите внимание, что sendMessages — это async, поэтому он возвращает обещание, но вы ничего не делаете с этим обещанием. Вы должны await на нем. Я соответствующим образом изменил ваш код и избавился от объектов context и callback, они вам не нужны.

const axios = require('axios');

const sendMessages = async (event) => {
  // test the message for a match
  if (event.type === 'message' && event.bot_id !== undefined) {
    console.info('filter events for specific event');

    let URL = 'https://someurl.com/slack/events';
    let response = await axios.post(URL, {
      events: event,
    });
    console.info('response success :: ', response.status);
    return response;
  }
  return Promise.resolve({});
};

// Lambda handler
exports.server = async (event) => {
  let eventData = JSON.parse(event.body);
  switch (event.path) {
    case '/slack-events':
      await sendMessages(eventData.event);
      break;
  }
  return {
    message: 'Success',
  }
};

Если эта лямбда вызывается API-шлюзом, вам нужно вернуть код состояния 2xx (или 4xx и 5xx в случае ошибок) со строковым телом, чтобы оно могло завершиться правильно, например так:

return {
        statusCode: 200,
        body: JSON.stringify({message: 'Success'})
      }

Спасибо за ответ. Это имеет смысл, и я соответствующим образом изменил лямбда-функцию, однако проблема не устранена. Теперь, когда я правильно ожидаю обещания sendMessages, должен ли я что-либо делать с ответом, чтобы завершить/выйти из функции в лямбда-обработчике?

dutterbutter 18.07.2019 12:00

Добро пожаловать. Не совсем... этот блок return { message: 'Success } должен справиться с этим. Если это не вызов из API-шлюза. Так ли это? Если это так, вам нужно добавить statusCode и преобразовать тело в строку. Я обновлю свой ответ.

Thales Minussi 18.07.2019 12:02

Другие вопросы по теме