簡體   English   中英

AWS Lambda SNS 發送主題兩次

[英]AWS Lambda SNS sending topic twice

TL; 博士

編寫一個 lambda 函數來執行一些數據庫查詢,然后給特定的用戶組發送電子郵件。

  • 為每個分享歌曲的群組發布 SNS 消息
  • 每個組都有自己的成員,因此有自己的一組電子郵件
  • SNS 主題為每個組發送兩次。

會員收到兩次電子郵件。

該應用程序是一個音樂流媒體應用程序,用戶可以在其中創作歌曲。 他們還可以創建群組、邀請成員加入這些群組並將他們的歌曲分享給這些群組。

這是通過 API 調用的 lambda:

  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 主題,它也會發送 2 個。當我將一首歌分享給 2 個群組時,它會發送 4 個 SNS 主題。

這是由 SNS 主題觸發的 lambda:

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 個主題,並不是 lambda 從同一個 SNS 被觸發兩次。

有沒有辦法解決?

我知道這個問題很老,但我發現自己也遇到了同樣的問題。 我解決了我的錯誤,我相信你也有同樣的問題。

.promise() publishSNS方法中的.promise() ,只需將其刪除(在下面注釋掉)。

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(); 
};

選擇的答案是正確的一半。

我也有同樣的問題。 您需要使用帶有回調的 SNS 或使用 SNS 在構造函數中設置 api 版本並使用promise()

const sns = new SNS({ apiVersion: '2010-03-31' });
await sns
  .publish(
    {
      Message: 'Message',
      TopicArn: <Arn>,
    },
  )
  .promise();

如果你沒有在構造函數中傳入 apiVersion 你必須傳入一個回調而不是使用promise()

我對 iotData 有相同的 pb,我用這樣的東西來解決我的問題

const request = iotdata.publish(mqttParams);
request
    .on('success', () => console.log("Success"))
    .on('error', () => console.log("Error"))
return new Promise(() => request.send());

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM