3

I found an odd behavior of AWS SNS when publishing multiple messages to Apple Push Notifications at the same time from AWS Lambda - every published message is received TWICE by the subscriber.

My code is as follows

handler.js

const uuid = require('uuid')
const aws = require('aws-sdk');
const sns = new aws.SNS({ apiVersion: '2010-03-31' })

const messageSender = async (event, context, callback) => {

  // sending 3 messages one after another
  publishMessage("title1", "message1")
  publishMessage("title2", "message2")
  publishMessage("title3", "message3")

  return []
}

const publishMessage = (title, message) => {

  sns.publish({
    Message: JSON.stringify({
      "default": "default message",
      "APNS_SANDBOX": JSON.stringify({
        "aps": {
          "alert": {
            "title": title,
            "body": message
          },
          "badge": 1,
          "id": uuid.v4(),
          "foo": "bar"
        }
      })
    }),
    MessageStructure: 'json',
    TopicArn: process.env.TOPIC_ARN
  }).promise()

  console.log(`Message for topic is published: ${message}`)
}

However if I publish only one message like the below, the exact message is received only once.

const messageSender = async (event, context, callback) => {

  publishMessage("title1", "message1")

  return []
}

Any ideas why receiving the same message twice when sending multiple messages?

EDIT

After playing the publish API a while I found the following.

The duplication is caused by a potential Amazon SNS bug(?). If not sending JSON format the duplication error disappears. e.g. Remove the MessageStructure: 'json' and change the message to be String only as follows.

sns.publish({
    Message: "this is a sample message",
    TopicArn: process.env.TOPIC_ARN
}).promise()

This is a workaround of the issue however the underlying cause of the original issue is still unknown.

The workaround has drawbacks as it cannot customise the notification with APN attributes such as adding a title to the push notifications as well as badges.

Any other workaround or whoever knows the fixes?

Conan
  • 355
  • 1
  • 4
  • 11

2 Answers2

4

I had the same problem, but the above didn't help.

In my case, I tracked it down to using a callback function AND the .promise() method.

i.e. I had something like:

await SNS.publish({
    TopicArn: process.env.SNS_TOPIC,
    Message: message,
    MessageAttributes: {
        source: {DataType: 'String', StringValue: source},
        level: {DataType: 'String', StringValue: level}
    },
}, function(err, data) {
    if (err) {
        console.log('SNS_notify: error -', err);
    } else {
        console.log('SNS_notify: sent -', data.MessageId);
    }
).promise();

Changing this to:

let data = await SNS.publish({
    TopicArn: process.env.SNS_TOPIC,
    Message: message,
    MessageAttributes: {
        source: {DataType: 'String', StringValue: source},
        level: {DataType: 'String', StringValue: level}
    },
}).promise();

console.log('SNS_notify: sent -', data.MessageId);

fixed the problem.

Mr Incredible
  • 441
  • 4
  • 8
  • Same exact problem as you two. I realized as soon as I saw your code snippets, that we all must have pulled from the same incorrect source: https://stackoverflow.com/a/51315070/1751883 – neuquen Oct 28 '21 at 20:46
  • The AWS SDK v2 supports callback style _or_ promises, but your first code snippet uses _both_. I'm not sure what `.promise()` returns on a request which was also passed a callback function. However, while the first code snippet is definitely incorrect, I can't explain why it would render duplicate messages. – JHH Apr 06 '22 at 09:15
1

After spending hours scratching my head I finally found the issue.

I added a customised id field in the json message which causes the same message being sent twice when publishing multiple messages same time.

After removed the id field, the messages are only sent once no matter how many messages are published at the same time.

{
  "default": "default message",
  "APNS_SANDBOX": JSON.stringify({
    "aps": {
      "alert": {
        "title": title,
        "body": message
      },
      "badge": 1,
      // "id": uuid.v4(),  <---- THIS LINE IS REMOVED
      "foo": "bar"
    }
  })
}

ps. I also noticed if the id remains, when publishing messages at an interval of more than 3 seconds, the same message is delivered once.

Conan
  • 355
  • 1
  • 4
  • 11