0

I'm coming to you guys again for help. I have an app, in which you can top up your own virtual wallet from your credit card.

My structure is as followers:

  • collection transactions/{transactionId} -- contains an owner UID and the top up amount.
  • collection users/{userId}/personal/wallet containing { funds: 0 }

I am keeping the wallet into a subcollection of personal info because I don't want other users to see it.

Anyway, I have an onCreate trigger called walletSync for new documents under transactions collection, from which I take the amount and add it to the user's current funds via runTransaction.

Problem is, the function sometime triggers three times ... for one document. Here's a screenshot. I have logged the transactionId ( which is just one document ) and as you can see, onCreate, is being processed three times, therefore, topping up my wallet with three times the actual value.

Here's my function code, in which I am marking any processed transaction with processed: true so I can ignore it next time it triggers. As you can see in the logs, that processed_already message never pops up, which means the trigger does not fetch the new data, next time it triggers.

I am out of ideas here, please advise.

EDIT: Here's my function: https://pastebin.com/PRA7CbxL

enter image description here

Eduard
  • 3,395
  • 8
  • 37
  • 62
  • Possible duplicate of [firestore cloud functions onCreate/onDelete sometimes immediately triggered twice](https://stackoverflow.com/questions/48735862/firestore-cloud-functions-oncreate-ondelete-sometimes-immediately-triggered-twic) – raina77ow Feb 21 '19 at 15:05
  • 1
    As suggested in that thread, one possible workaround is checking whether or not the corresponding transactionId has already been processed. – raina77ow Feb 21 '19 at 15:07
  • I was in a hurry and did not get to mention that I am already marking those documents with a field called `processed` as `true`. Either way, it's simply not taking that into account. – Eduard Feb 21 '19 at 15:51
  • I have gone through all idempotency threads on stackoverflow, none actually explains how to work around the issue. Only thing I found was that eventId which should be unique. But since my processed field is not taken into consideration, that wouldn't help either. – Eduard Feb 21 '19 at 15:52
  • You really need to make use of that unique event id. That's your main tool for implementing correct idempotency. – Doug Stevenson Feb 21 '19 at 16:07
  • @DougStevenson quick question, as I can't find it in the EventContext description. Will this eventId be the same in case of multiple function triggers for same event ? – Eduard Feb 21 '19 at 16:11
  • Yes, that's its entire reason for existence. – Doug Stevenson Feb 21 '19 at 16:51
  • Ok cool. I've adapted my code after the mentioned similar thread, code is here: https://pastebin.com/PRA7CbxL Now, given that code which obviously check if that `eventId` is the same between the two triggers, ( and it is, as seen in the logs here: https://i.imgur.com/uCabwCv.png ) you can also see that the `item.processed` ( which should be the last event Id ) is undefined in both cases. I'm trying to ... actually, damn I'm stupid. snapshot.data() will never have the last eventId in it because it's always the event data that is passed towards the trigger function, and not the latest state. – Eduard Feb 21 '19 at 17:08

1 Answers1

0

I have managed to figure it out, with the help of the mighty @Doug and the mentioned similar questions.

After all, the issue with my code was that while I was marking my transaction as processed, I was assuming that the second / third time the function triggers, snapshot.data() would be the value of the document, ( took me some time to realize ) it was actually the change data sent towards the database trigger. I know it sounds confusing, but the function is not being sent the value of the document ( for that you could get snapshot.ref and fetch the data from there, in order to get the updated value in a transaction ).

So here's my updated function on Pastebin. Here's a screenshot of the code in action: https://i.stack.imgur.com/5TeNh.png

Eduard
  • 3,395
  • 8
  • 37
  • 62