AWS Lambda SNS отправляет topi c дважды - PullRequest
0 голосов
/ 16 марта 2020

TL; DR

Написание лямбда-функции для выполнения некоторых запросов к БД, а затем по электронной почте определенным группам пользователей.

  • publi sh Сообщение SNS для каждой группы, для которой предназначена песня общий доступ к
  • У каждой группы есть свои участники, таким образом, ее собственный набор электронных писем
  • темы SNS отправляются дважды для каждой группы.

Участники получают электронное письмо дважды.

Приложение представляет собой потоковое приложение musi c, где пользователи могут создавать песни. Они также могут создавать группы, приглашать участников в эти группы и делиться своими песнями с этими группами.

Вот лямбда, вызываемая через API:

  const shareWithGroup = async event => {
  const { songCuid, groupCuids } = JSON.parse(event.body);
  const shareSongDB = await query(
    sql.queryShareWithGroup(songCuid, groupCuids),
  ); //share to group in DB
  if (!shareSongDB) {
    return corsUtil.failureWithCors("Couldn't Share Song with group");
  }
  const song = await query(sql.queryRead(songCuid));
  if (!song) {
    return corsUtil.failureWithCors('Song doesnt exist');
  }
  const songTitle = song.rows[0].songTitle; //retrieve songTitle
  const promises = groupCuids.map(async groupCuid => {
    console.log('GROUP_CUID', groupCuid);
    const emailResults = await query(sql.queryReadGroupEmails(groupCuid)); // get emails for group + groupName
    const results = emailResults.rows;
    const groupName = results[0].groupName;
    let emails = [];
    results.map(row => {
      emails.push(row.email); //push email address into array
    });
    const payload = JSON.stringify({ groupName, emails, songTitle }); //send groupName, emails list and songTitle to SNS to trigger email
    console.log(payload);
    await publishSNS(payload)
    //send the topic
  });

  //Resolve all promises
  await Promise.all(promises);
  console.log(promises);
  return corsUtil.successWithCors('Success');
};

const publishSNS = async payload => {
  console.log('publishing sns topic');
  //SEND EMAILS
  const params = {
    Message: payload,
    TopicArn: `arn:aws:sns:eu-west-1:${process.env.AWS_ACC_ID}:${process.env.STAGE}-songShareTrigger`,
  };

  return await sns
    .publish(params, async error => {
      if (error) {
        console.error(error);
        //TODO: Actually fail the function - can't do with lambdaFactory
      }
    })
    .promise();
};

И пример запроса (поделиться песней в 1 группу):

{"songCuid":"XXX","groupCuids":["XXX"]}

Проблема в том, что каким-то образом, хотя он должен отправлять только 1 SNS topi c, он отправляет 2. Когда я делю песню на 2 группы, она отправляет 4 Темы SNS.

Вот лямбда, запускаемая SNS topi c:

const aws = require('aws-sdk');
const ses = new aws.SES();
const corsUtil = require('../utils/corsUtil');

exports.songShareEmail = (event, context) => {
  console.log('EVENT : ', event.Records[0].Sns); // LOG SNS
  const body = JSON.parse(event.Records[0].Sns.Message);
  const { groupName, emails, songTitle } = body;
  console.log('Body : ', body);

  const groupInviteEmailData = `
      <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
      <html>
      <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
      </head>
      <body>
        <div class="email-body" style="max-width:900px; margin:auto;" >
          <div class="content" style="background-color:white; margin:0 auto; 
            display:block;">
            <p>Hello<p>
            </br>
            A new song has been shared to the group : <u>${groupName}</u><br>
            <h3>Song Title: ${songTitle}</h3>

          </div>
        </div>
      </body>
      </html>
  `;

    var params = {
        Destination: {
          ToAddresses: emails,
        },
        Message: {
          Body: {
            Html: {
              Charset: 'UTF-8',
              Data: groupInviteEmailData,
            },
          },
          Subject: {
            Charset: 'UTF-8',
            Data: `New song shared to ${groupName}`,
          },
        },
        Source: 'xxx',
      };
      console.log('sendingEmail');
      ses.sendEmail(params, function(err) {
        if (err) {
          console.log(err);
          const response = corsUtil.failureWithCors(err);
          context.fail(response);
        } else {
          context.succeed('Done');
        }
      });
    };

Я зарегистрировал объект SNS из события, и я вижу, что это каждый раз новый MessageId означает, что он на самом деле отправляет 2 темы каждый раз, и это не значит, что лямбда запускается дважды с одного и того же SNS.

Есть ли способ обойти это?

...