0

I have configured my push notifications using the node apn library.

I use an AWS lambda function to send the notification and it is called from another lambda function using event as the invocation type as follows:

var pushPayload = { "users": users, "message": message };

var pushParams = {
    FunctionName: 'function-name',
    InvocationType: 'Event',
    LogType: 'Tail',
    Payload: JSON.stringify(pushPayload)
};

lambda.invoke(pushParams, function (err, data) {
    if (err) {
        callback(error);
    } else {
        callback(null, event.arguments.input);
    }
});

and the send notification lambda function:

var options = {
    token: {
        key: "key",
        keyId: keyId,
        teamId: teamId
    },
    production: true
};
var message = event.message;
var users = event.users;

var apnProvider = new apn.Provider(options);

var iterationComplete = false;

for (var j = 0; j < users.length; j++) {
    if (j === (users.length - 1)) {
        iterationComplete = true;
    }

    var deviceToken = users[j].user_device_token;

    var notification = new apn.Notification();

    notification.alert = message;

    notification.contentAvailable = 1;

    notification.topic = "com.example.Example";

    context.callbackWaitsForEmptyEventLoop = false;
    apnProvider.send(notification, [deviceToken]).then((response) => {
        if (iterationComplete) {
            context.succeed(event);
        }
    });
}

Sometimes the notifications get out of sync and when I send a message which sends it's push notification, the notification from the previous message is received. Not sure why this is happening or how to fix it.

alionthego
  • 8,508
  • 9
  • 52
  • 125
  • 1
    This is potentially a side effect of using `context.callbackWaitsForEmptyEventLoop = false;` incorrectly/inappropriately, since it can mask other bugs. Why are you disabling this? What is `iterationComplete` and how does it get set? (Speculation: you're sending more than one, but only waiting for the last one started to finish, forgetting that last to start is not necessarily last to finish.) – Michael - sqlbot Aug 26 '18 at 16:09
  • Thanks @Michael - sqlbot. As you correctly assumed I am trying to send multiple messages and hence the iteration. Also, I am not very familiar with context.callbackWaitsForEmptyEventLoop so I will look into that further. I have updated the code to show the iteration. – alionthego Aug 26 '18 at 20:43
  • not sure now where to put the context.succeed(event) so that all notifications will be sent before the code is terminated. – alionthego Aug 26 '18 at 20:55
  • 1
    `callbackWaitsForEmptyEventLoop`, when `true` (the default) prevents a premature callback from returning a response immedately and suspending the container. Disabling it is useful -- indeed, mandatory -- in certain cases, such as a database connection that you want to keep alive between subsequent invocations for reuse... but it also enables behavior like you are seeing here -- unfinished work will continue during the next function invocation that happens to reuse the same container. – Michael - sqlbot Aug 26 '18 at 23:03
  • Thanks Michael. I've removed that line and it seems to be working fine. I have used that with database connections in the past and was incorrectly propagating it here. If you mark that as an answer I will be happy to accept it. cheers. – alionthego Aug 26 '18 at 23:14

0 Answers0