Node.js AWS Lambda SNS发送主题两次 TL;博士
编写lambda函数来执行一些数据库查询,然后通过电子邮件发送给特定的用户组Node.js AWS Lambda SNS发送主题两次 TL;博士,node.js,aws-lambda,amazon-sns,serverless,amazon-ses,Node.js,Aws Lambda,Amazon Sns,Serverless,Amazon Ses,编写lambda函数来执行一些数据库查询,然后通过电子邮件发送给特定的用户组 为每个共享歌曲的群组发布SNS消息 每个小组都有自己的成员,因此有自己的一套电子邮件 每个小组发送两次SNS主题 会员们收到了两封电子邮件 该应用程序是一个音乐流应用程序,用户可以在其中创建歌曲。他们还可以创建群组,邀请成员加入这些群组,并将他们的歌曲分享给这些群组 以下是通过API调用的lambda: const shareWithGroup = async event => { const { s
- 为每个共享歌曲的群组发布SNS消息
- 每个小组都有自己的成员,因此有自己的一套电子邮件
- 每个小组发送两次SNS主题
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个SNS主题,它也会发送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');
}
});
};
const aws=require('aws-sdk');
const ses=新的aws.ses();
const corsUtil=require('../utils/corsUtil');
exports.songsharemail=(事件、上下文)=>{
console.log('EVENT:',EVENT.Records[0].Sns);//log Sns
const body=JSON.parse(event.Records[0].Sns.Message);
const{groupName,email,songtTitle}=正文;
log('Body:',Body);
const groupInviteEmailData=`
你好
已将一首新歌共享给组:${groupName}
歌曲名称:${songTitle}
`;
变量参数={
目的地:{
地址:电子邮件,
},
信息:{
正文:{
Html:{
字符集:“UTF-8”,
数据:分组数据,
},
},
主题:{
字符集:“UTF-8”,
数据:`New song shared to${groupName}`,
},
},
资料来源:“xxx”,
};
console.log(“发送电子邮件”);
ses.sendEmail(参数、函数(错误){
如果(错误){
控制台日志(err);
const response=corsUtil.failureWithCors(err);
上下文。失败(响应);
}否则{
context.success('Done');
}
});
};
我已经从事件中记录了SNS对象,并且我可以看到它每次都是一个新的MessageId,这意味着它实际上每次发送2个主题,而不是lambda从相同的SNS被触发两次
这有什么办法吗 我知道这个问题由来已久,但我发现自己也有同样的问题。我解决了我的错误,我相信你也有同样的问题 您的
publishSNS
方法中的.promise()
是不需要的,只需删除它即可(在下面注释掉)
我对IoData使用了相同的pb,我使用类似的方法来解决我的问题
const request = iotdata.publish(mqttParams);
request
.on('success', () => console.log("Success"))
.on('error', () => console.log("Error"))
return new Promise(() => request.send());
选择的答案是正确的一半 我也有同样的问题。您需要将SNS与回调一起使用,或者使用SNS在构造函数中设置api版本并使用
promise()
const sns=新的sns({apiVersion:'2010-03-31'});
等待sns
.出版(
{
消息:“消息”,
TopicArn:,
},
)
.promise();
如果您没有在构造函数中传入apiVersion,那么您必须传入回调,并且在我弄明白时不要使用
promise()
完全忘记了更新它-您所解释的正是问题所在。花了我这么多时间,但肯定是我自己的失误。要添加到您的答案中-不需要.promise()的原因是因为我使用的是async-如果没有async,我将需要.promise()。谢谢你的更新!我也有同样的问题,但当我漏掉“.promise()”时,我不会收到任何邮件。当我添加它时,我会收到两次邮件:-/。如果您删除promise()
您是正确的,那么也不需要使用wait,这应该是公认的答案!
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();
};
const request = iotdata.publish(mqttParams);
request
.on('success', () => console.log("Success"))
.on('error', () => console.log("Error"))
return new Promise(() => request.send());
const sns = new SNS({ apiVersion: '2010-03-31' });
await sns
.publish(
{
Message: 'Message',
TopicArn: <Arn>,
},
)
.promise();