publi sh сообщение для sns topi c от lambda - PullRequest
2 голосов
/ 27 марта 2020

У меня есть лямбда-функция, которая обрабатывает запрос POST через AWS лямбда-функцию. Он обрабатывает тело почтового запроса, создает запрос и возвращает ответ.

МОЯ ФУНКЦИЯ LAMBDA

const { Pool, Client } = require("pg");
const userName = 'blah';
const hostEndPoint = 'blah';
const databaseType = 'blahblah';
const pwd = 'pass pass';
const portNumber = 5432;
var AWS = require('aws-sdk');

const pool = new Pool({
  user: userName,
  host: hostEndPoint,
  database: databaseType,
  password: pwd,
  port: portNumber
});


exports.handler = async (event) => {
  let body = JSON.parse(event.body);
  let name = body.name;
  let money = body.money;
  let todayDate = new Date();
  var status = 0;
  let text = 'INSERT INTO employee(name, date, salary) VALUES($1, $2, $3) RETURNING *';
  let values = [name, todayDate, money];
  var message = '';
  var status = 0;

  try {
    const res = await pool.query(text, values)
    message += 'successful'
    status = 200;
  } catch (err) {
    message += 'unsuccessful'
    if (err.code === '23505') {
      status = 406;
    }
  }

  var params = {
    Message: 'Hello From Lambda', /* required */
    TopicArn: 'arn:aws:sns:us-east-1:blahblahblah'
  };

  // Create promise and SNS service object
  var publishTextPromise = new AWS.SNS({ apiVersion: '2010-03-31' }).publish(params).promise();

  publishTextPromise.then(
    function (data) {
      console.log(`Message ${params.Message} send sent to the topic ${params.TopicArn}`);
      console.log("MessageID is " + data.MessageId);
    }).catch(
      function (err) {
        console.error(err, err.stack);
      });



  const response = {
    statusCode: status,
    body: JSON.stringify(message),
    headers: {
      "Access-Control-Allow-Origtin": '*'
    }
  };
  return response;
};

Моя Политика лямбда-ресурсов Похоже на это

{
  "Version": "2012-10-17",
  "Id": "default",
  "Statement": [
    {
      "Sid": "blah-blah-blah-blah",
      "Effect": "Allow",
      "Principal": {
        "Service": "apigateway.amazonaws.com"
      },
      "Action": "lambda:InvokeFunction",
      "Resource": "arn:aws:lambda:us-east-1:blah-blah-blah-blah-blah",
      "Condition": {
        "ArnLike": {
          "AWS:SourceArn": "arn:aws:execute-api:us-east-1:blahblahblahblha:blah/*/POST/"
        }
      }
    }
  ]
}

Я также создал SNS topi c. Я хочу опубликовать sh сообщение для SNS topi c, если мой статус 200. Поэтому, прежде чем я верну ответ. Я хочу сделать что-то вроде этого.

if (status === 200){
  pubish some message to my sns topic
}

Я очень плохо знаком с aws и хотел бы получить несколько советов о том, как я могу опубликовать sh сообщение. Я чувствую, что я рядом. Я сталкивался с этим topi c, но это сбивает меня с толку, потому что я редактирую код в лямбда-функции, так почему я должен требовать aws -sdk, а также они не говорят об изменении разрешения ,

Обновлен код после попытки ниже предложенного ответа

Ответы [ 2 ]

1 голос
/ 27 марта 2020

Как видите, строка return response; будет запущена немедленно, когда publish не завершит sh свою задачу - опубликовает sh сообщение для SNS. Поскольку publish, publishTextPromise.then и return являются просто кодами синхронизации, потребуется всего один тик (~ 0,00..1 секунды), чтобы завершить sh. Когда для функции-обработчика был вызван return, функция завершится sh, это означает, что все выполняемые задачи будут отменены (включая publish процесс, процессу нужно слишком много времени (~ <1 с и> один тик) до конца sh).

Вы смешиваете синтаксис async/await с синтаксисом обещания (.then .catch), тогда процесс не будет работать так, как вы думаете (или хотите), я рекомендую просто использовать синтаксис async/await если можете.

С вашим кодом, я гостю, задача publish не повлияет на ответ, она просто попытается опубликовать sh сообщение в SNS. Мое предложение, изменить

  publishTextPromise.then(
    function (data) {
      console.log(`Message ${params.Message} send sent to the topic ${params.TopicArn}`);
      console.log("MessageID is " + data.MessageId);
    }).catch(
      function (err) {
        console.error(err, err.stack);
      });
Добавлено ключевое слово от

до

  await publishTextPromise // wait until the task done
    .then((data) => {
      console.log(`Message ${params.Message} send sent to the topic ${params.TopicArn}`);
      console.log("MessageID is " + data.MessageId);
    })
    .catch((err) => {
      console.error(err, err.stack);
    });

await, и я предпочитаю синтаксис функции стрелки

1 голос
/ 27 марта 2020

Я предполагаю, что ваша архитектура выглядит примерно так:

API-шлюз принимает запрос и вызывает лямбда-функцию, которую вы нам показали. Эта лямбда-функция подключается к базе данных и вставляет запись. Теперь вы хотите, чтобы эта лямбда-функция также публиковала sh в SNS topi c.

. Для этого вам нужно сделать две вещи:

  1. Предоставить лямбда-функцию разрешения для SNS topi c
  2. Записать код для publi sh сообщение для topi c

Шаг 1 должен стоять первым и для этого вам нужно отредактировать роль IAM, которую использует ваша функция. Роль IAM определяет, какие AWS сервисы разрешено вызывать этой лямбда-функции. Лямбда-ресурсная политика, которую вы показали нам, предоставляет шлюзу API разрешения для вызова / вызова вашей лямбда-функции - это никак не влияет на то, что функция может делать.

Если это только для тестирования, вы можете найти роль IAM функции в Identity and Access Management и присоединение политики AmazonSNSFullAccess - не делайте этого для любой производственной среды, это дает намного больше разрешений, чем необходимо добавьте пользовательскую политику, которая разрешает действие sns:Publish только для вашей топи c).

Теперь ваша функция имеет права на публикацию sh сообщений в вашу топи c.

Шаг 2 означает, что вам нужно отредактировать ваш код. Импорт AWS SDK, как описано в документации , которую вы связали , необходим, потому что вы хотите, чтобы ваш код взаимодействовал со службами AWS - для этого вам нужен SDK. Другие шаги в этой документации кажутся разумными, за исключением установки региона, вам не нужно делать это, если ваш topi c живет в том же регионе AWS, что и ваша лямбда-функция.

Некоторые дополнительные наблюдения / предложения:

  • В вашем CORS-заголовке есть опечатка Access-Control-Allow-Origtin - это должен быть Origin. Вы также можете установить это в шлюзе API, так что ваша функция не должна об этом заботиться.
  • Я рекомендую вам получить учетные данные вашей базы данных из чего-то вроде AWS Secrets Manager или System Manager Parameter Храните вместо того, чтобы хранить их в коде
  • Установив пул соединений вне обработчика, вы дадите своему коду возможность повторно использовать существующие DB-соединения, молодец!
...