После долгой проверки всех логов и понимания сценария моей инфраструктуры я решил проблему. Давайте сначала разберемся с ситуацией лучше:
Подробнее о сценарии:
Я проверил, какие максимальные допустимые значения для тайм-аута в 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 получает ожидаемый статус, и мой бот работает параллельно. Теперь, возможно, вы ожидаете окончательный код. Поэтому я поделюсь им с вами.
Код:
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: ''})
}
const bot = require('./Bot')
exports.handler = function(event) {
const tmp = JSON.parse(event.body)
bot.handleUpdate(tmp)
}
Дополнительный совет:
Вашему Lambda 1 понадобятся необходимые роли для запуска Лямбда 2. Если вы включите CloudWatch Logs, он предоставит вам всю необходимую роль, но я поделюсь ролью, которую я установил ниже: