4

Hello my firebase cloud function gets called multiple times when I don't put in check for previous.exists(). I get multiple push notifications.

if (!event.data.exists()){
    return;
}
if (event.data.previous.exists()){
    return;
}

But when I check for it i don't get push notification. Here is the not working code: What should I change?

exports.sendShoppingListInvitationNotification = functions.database.ref('/invites/{id}/').onWrite(event => {
//get the snapshot of the written data
const snapshot = event.data;  

if (!event.data.exists()){
    return;
}
if (event.data.previous.exists()){
    return;
}

    //get snapshot values
    console.log(snapshot.key);
const receiptToken = snapshot.child('receiptFcmToken').val();
const senderName = snapshot.child('senderNickname').val();
const inviteMessage = snapshot.child('inviteMessage').val();
const senderImage = snapshot.child('senderProfileImageURL').val();


//create Notification
const payload = {
    notification: {
        title: `Invitation from ${senderName}`,
        body:  `${inviteMessage}`,
        icon: `${senderImage}`,
        badge: '1',
        sound: 'default',
    }
};               

//send a notification to firends token   
return admin.messaging().sendToDevice(receiptToken, payload).then(response => { 
     console.log("Successfully sent message:", response);
 }).catch((err) => {
    console.log(err);
});   
});

I don't get error message on cloud console.

This is the firebase structure: enter image description here

AL.
  • 36,815
  • 10
  • 142
  • 281
Peter Sypek
  • 151
  • 2
  • 12

1 Answers1

8

Seems like it shouldn’t be called multiple times unless you’re doing multiple writes to that location. Try using .onCreate instead of .onWriteif you only want to send a notification on the first write to the path. Then you won’t need that check for previous data. See the documentation here which outlines the different database triggers.

Jen Person
  • 7,356
  • 22
  • 30
  • 1
    great Idea. I just watched your tutorial. Its an honor to get answerd by an expert. – Peter Sypek Aug 27 '17 at 18:48
  • Sad I just don't get my data now. The onCreate function delivers null for the receiptFcmToken. Error: Registration token(s) provided to sendToDevice() must be a non-empty string or a non-empty array. – Peter Sypek Aug 27 '17 at 19:24
  • I think i got a idea when i call onWrite my function executes on each childnode when it is added. The onCreate delivers the an empty node just when it is created and before childs added I think. But how i get the child values. Iam little confused. – Peter Sypek Aug 27 '17 at 19:44
  • How are you adding the data to the database? I tested out your code and it works as expected. However, if you are adding some of the children of each `id` one at a time or in groups rather than as one child, the function will be called for each addition. What's the code that adds the data to the database? – Jen Person Aug 27 '17 at 22:31
  • Thank you @Jen thats the solution. I die not write the data at once. I need to use the setValues method with an array of key value pairs. – Peter Sypek Aug 28 '17 at 03:29
  • There is one question left I want to ask you. Would you suggest to use a thread safe array for firebase because of often async data calls? – Peter Sypek Aug 28 '17 at 03:43
  • 2
    Seems assuming cloud firestore triggered functions will only execute one time is not safe: See here https://stackoverflow.com/questions/48735862/firestore-cloud-functions-oncreate-ondelete-sometimes-immediately-triggered-twic and here: https://stackoverflow.com/questions/49217120/how-to-make-idempotent-aggregation-in-cloud-functions/50860068#50860068 I had this issue with an aggregation. Really think docs should be changed to highlight this: https://firebase.google.com/docs/firestore/solutions/aggregation#solution_cloud_functions Could happen rarely and be painful bug if not idempotent. – cdock Sep 15 '18 at 02:17
  • Echoing @cdock, this happens to me on a regular basis. I observed it as soon as i switched function region to match the firestore region. – Alex Suzuki Apr 30 '19 at 19:17
  • Moving the function back to the default region us-central1 helped, have not seen any duplicate invocations so far. Not a solution, but probably still helpful to some. – Alex Suzuki Apr 30 '19 at 19:24