Программируемое SMS-сообщение Twilio не отправляется в развернутой лямбда-функции

Я работаю над сервисом AWS Serverless, который использует Программируемое SMS от Twilio для доставки текстовых сообщений.

Моя установка постоянно успешно доставляет сообщения, когда я запускаю стек локально (например, sls offline start), но в развернутой среде я, похоже, не могу даже вызвать метод на Клиент Twilio.

Вот как настраивается доставка сообщений:

const twilio = require('twilio');

const twilioClient = twilio(
  process.env.TWILIO_SID,
  process.env.TWILIO_TOKEN,
  {
    lazyLoading: true,
  }
);

export function sendMessage(user, message) {
  twilioClient.messages.create({
    from: process.env.TWILIO_NUMBER,
    to: user.phone,
    body: message,
  }, function(err, message) {
    console.log('error', err);
    console.log('message', message);
  });
}

// And then usage in a Serverless Function Handler

function example(event, context, callback) {
  context.callbackWaitsForEmptyEventLoop = false;

  // user is also determined here
  sendMessage(user, 'This is a message');

  return {
    body: JSON.stringify({}),
    statusCode: 200
  };
}

Локально это работает, и я могу видеть результат message журнала, а в error журнале ничего нет. Однако при развертывании выполнение этого ничего не дает - метод, похоже, даже не вызывается (и я могу проверить в журналах Twilio, что не было выполнено ни одного вызова API), поэтому в обратном вызове не ведутся журналы error или message.

При отладке пробовал следующее:

  • Я зарегистрировал все переменные среды (Twilio SSID, токен аутентификации, номер телефона), а также аргументы функции, и все они кажутся на месте. Я также проверил саму лямбда-функцию, чтобы убедиться, что переменные среды существуют.
  • Я изучил свои журналы CloudWatch; никаких ошибок или исключений не регистрируется. Кроме того, что метод Twilio не вызывается, функция Lambda выполняется без проблем.
  • Я пробовал регистрировать такие вещи, как twilio и twilioClient.messages.create, чтобы убедиться, что определение клиента и функции каким-то образом не было уничтожено.
  • Я подумал, может быть, это связано с context.callbackWaitsForEmptyEventLoop, поэтому я изменил его с false на true.

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


Изменить: в соответствии с примером клиента Twilio, если вы опустите функцию обратного вызова, метод вернет обещание. Я пошел дальше и попытался дождаться ответа метода:

export function sendMessage(user, message) {
  return twilioClient.messages.create({
    from: process.env.TWILIO_NUMBER!,
    to: user.phone,
    body: message,
  });
}

// Usage...

async function example(event, context, callback) {
  context.callbackWaitsForEmptyEventLoop = false;

  try {
    const message = await sendMessage(user, 'This is a message');
    console.log('message', message)
  } catch (error) {
    console.log('error', error);
  }

  return {
    body: JSON.stringify({}),
    statusCode: 200
  };
}

В этом примере лямбда-функция выполнена успешно, но ни сообщение, ни ошибка не регистрируются.


person Jody Heavener    schedule 26.04.2020    source источник
comment
Я не использовал Lambda, но с функциями Twilio вы должны помнить об асинхронных функциях и связанном обратном вызове, чтобы указать конец функции, а именно - twilio.com/docs/runtime/functions/. Может ли это быть тем, что происходит и в этом случае? Может здесь какие-нибудь подробности? docs.aws.amazon.com/lambda/latest/dg/ nodejs-handler.html   -  person Alan    schedule 27.04.2020
comment
@Alan Я подозреваю, что вы что-то знаете, но, к сожалению, я не смог решить эту проблему. Я обновил свой вопрос, чтобы отметить, что я попробовал метод на основе обещаний, но безуспешно.   -  person Jody Heavener    schedule 27.04.2020


Ответы (1)


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

const twilio = require('twilio');

const twilioClient = twilio(
  process.env.TWILIO_SID,
  process.env.TWILIO_TOKEN
);

let user = '+14075551212';

function sendMessage(user, message) {
  return twilioClient.messages.create({
    from: process.env.TWILIO_NUMBER,
    to: user,
    body: message,
  });
}

exports.handler = async function(event, context, callback) {
  try {
    const message = await sendMessage(user, 'This is a message');
    console.log('message', message);
    callback(null, {result: 'success'});
  } catch (error) {
    console.log('error', error);
    callback("error");
  }
};
person Alan    schedule 27.04.2020
comment
Спасибо за это, Алан! Конечно, как вы упомянули, это работает так, как написано. Я отмечу это как ответ. К сожалению, в моем случае я думаю, что происходит что-то еще, и я думаю, что это VPC, который я настроил для функции Lambda. Это необходимо для связи с экземпляром RDS, и я думаю, что где-то там он блокирует исходящие запросы к Twilio. Я не упомянул об этом в своем исходном посте, приношу свои извинения. Если у вас есть какие-либо знания о VPC / подсети / NAT-шлюзе, я все слышу. В противном случае спасибо за этот ответ! - person Jody Heavener; 28.04.2020
comment
Привет, Джоди, я знаю, но не по моей специальности. Может быть, лучше для другого поста. Схема вашей топологии поможет другим дать более конкретный ответ. Обычно я думаю, что разрешения IAM - это больше проблема с Lambda, но я действительно не так много работал с ней, хотя 100% в моем растущем списке дел. - person Alan; 28.04.2020