AWS Лямбда - Telegram Bot с MySQL - L oop Сообщение \ Такое же сообщение - PullRequest
1 голос
/ 16 апреля 2020

Я разрабатываю AWS лямбда-функцию для размещения моего Telegram Bot.

Детали проекта:

  • Используется webhook (API Gateway) ;
  • Лямбда-функция будет получать сообщения Telegram и проверять базу данных;
  • Я использую MYSQL для хранения пользователей и некоторых сведений.

Простой рабочий процесс:

  • Пользователь отправляет сообщение телеграммы -> Telegram Webhook -> Шлюз API -> AWS Лямбда -> MYSQL Запрос -> Ответ для пользователя Telegram

Код

  • Индекс. js

    const bot = require('./Bot')
    exports.handler = function(event, context, callback) {
        const tmp = JSON.parse(event.body)
        bot.handleUpdate(tmp)
        .then(() => {
            var response = {"statusCode": 200, "body": "OK"}
            //callback(null, response)
            //context.succeed(response)
        })
    }
    

В боте. js, есть MYSQL Запрос, чтобы проверить, отправляет ли пользователь сообщение под разрешенными днями и часами.

Проблема:

Если я использую обратный вызов (ноль, ответ)

  • Запрос выполняется правильно;
  • Пользователь получает ответить.

В этом случае я продолжаю получать одно и то же сообщение от webhook в al oop. Насколько я мог видеть, ответ не работает

Если я использую context.succeed (response)

  • Запрос НЕ выполняется ;
  • Пользователь НЕ получает ответ .

В этом случае я получаю исходное сообщение только один раз.

Кто-нибудь знает, что может решить эту проблему. Я уже пытался использовать контекст и обратный вызов, но запрос не выполняется, и пользователь не получает ответ.

1 Ответ

0 голосов
/ 17 апреля 2020

После долгой проверки всех логов и понимания сценария моей инфраструктуры я решил проблему. Давайте сначала разберемся с ситуацией лучше:

Подробнее о сценарии:

Я проверил, какие максимальные допустимые значения для тайм-аута в API Gateway и Лямбда:

  • Лямбда: Максимум 15 минут
  • Шлюз API: Максимум - 30 секунд

После понимания этих значений я начал проверять журнал функций лямбда-функции:

  • Исходный код: 1 минута до финиша sh выполнение
  • Улучшенный код: 40 секунд до окончания sh выполнения

Как вы можете видеть, даже после улучшения моего кода он не заканчивался до истечения времени ожидания шлюза API. Это вызвало проблему, с которой я столкнулся.

Если вы проверите информацию о Telegram Webhook:

Я снова и снова получал одно и то же сообщение в статусе ожидания. Это было причиной l oop в полученных сообщениях. Если вы не ответите на Telegram Webhook со статусом 200, Он продолжит отправлять вам это сообщение.

Вернуться к Простому рабочему процессу

  • Пользователь отправляет сообщение телеграммы -> Telegram Webhook -> Шлюз API -> AWS Лямбда -> MYSQL Запрос -> Ответ пользователю Telegram

Проблема возникает между Telegram Webhook и API Gateway. Так как моей лямбда-функции требуется более 30 секунд до окончания sh, наш API-шлюз никогда не отправит ответ. Это заставляет Telegram Webhook продолжать посылать одно и то же сообщение снова и снова.

Мой поиск, чтобы решить его:

Нам нужно отправить ответ обратно при тайм-ауте шлюза API (30 секунд), но мы также должны поддерживать нашу функцию Lambda до тех пор, пока она не будет завершена с ожидаемым результатом.

После поиска я нашел topi c: Nodejs - Вызвать AWS. Лямбда-функция из другой лямбда-функции

Если мы вызовем вторую лямбду, мы можем запустить ее параллельно, пока первая лямбда может отправить ожидаемый ответ для Telegram Webhook.

Решение:

Основано на этой топике c Я немного проверил, как можно запустить вторую лямбда-функцию, не дожидаясь ответа, и ответа было: "Лямбда как СОБЫТИЕ "

Подробнее здесь: https://docs.aws.amazon.com/lambda/latest/dg/lambda-invocation.html

Как этот топи c объясняет, если вы вызовете лямбда-функцию в качестве СОБЫТИЯ, что произойдет:

  • Лямбда 1 -> Вызвать Лямбду 2
  • Лямбда 2 -> Состояние отправки 202 для Лямбды 1
  • Lambda 1 -> Состояние отправки 200 для Telegram Webhook
  • Lambda 2 -> Продолжить работу до конца sh Задание

Это решило всю проблему.

Теперь Telegram Webhook получает ожидаемый статус, и мой бот работает параллельно. Теперь, возможно, вы ожидаете окончательный код. Поэтому я поделюсь им с вами.

Код:

  • Лямбда 1
    AWS = require('aws-sdk');
    AWS.config.region = 'sa-east-1';  //Change for your own region
    var lambda = new AWS.Lambda();

    exports.handler = function(event, context, callback) {
    console.log(event)
    var params = {
      FunctionName: 'Lambda Function Name',
      InvocationType: 'Event',
      Payload: JSON.stringify(event)
    };

    lambda.invoke(params, function(err, data) {
      if (err) {
        console.log(err)
      }
    })
      callback(null, {statusCode: 200, body: ''})
    }
  • Lambda 2

    const bot = require('./Bot')

    exports.handler = function(event) {
        const tmp = JSON.parse(event.body)
        bot.handleUpdate(tmp)
    }

Дополнительный совет:

Вашему Lambda 1 понадобятся необходимые роли для запуска Лямбда 2. Если вы включите CloudWatch Logs, он предоставит вам всю необходимую роль, но я поделюсь ролью, которую я установил ниже:

enter image description here

...