Firebase Cloud feature launches twice onUpdate

I have rules set for my firebase collection - payments

 "payments": { "$paymentId": { "totalAmount": { }, "balanceAmount": { ".validate": "newData.val()<=data.child('totalAmount').val()" }, "paymentDetails": { "$detailId": { "amount": { ".validate": "newData.isString()" }, } }, } } 

and below a cloud function written to handle specific updates in this collection:

 exports.calculateBalance = functions.database .ref('payments/{pushId}') .onUpdate(event => { const paymentRef = event.data.adminRef; const payment = event.data.val(); return paymentRef.once('value').then(snapshot => { var paidAmount = 0; snapshot.child("paymentDetails").forEach(function(child) { paidAmount += parseFloat(child.child("amount").val()); }); return paidAmount; }).then(snap => { payment.balanceAmount = parseFloat(payment.totalAmount) - snap; return paymentRef.set(payment); }) }); 

Just when I add payment details I want to update balanceAmount . The problem here is that whenever an update occurs in this collection, the function runs twice . The first time it is obvious from the application and the second time it is because of the line paymentRef.set(payment); .

Is there any possible way to avoid this second trigger on the cloud function? I can’t use any flag at collection level, because payment information is updated several times. Can someone direct me in the right direction?

EDIT

Note. I have an edit option for the entered payment data.

+5
source share
1 answer

If you want to update the balance balance only when adding payment information, you can use the onCreate trigger directly on the payment details.

Try something like this (you need to update the code for your case):

 exports.calculateBalance = functions.database.ref('payments/{pushId}/paymentDetails/{detailId}').onCreate(event => { var paymentRef = event.data.adminRef.parent.parent; var paymentDetailSnapshot = event.data; var paymentDetailAmountSnapshot = paymentDetailSnapshot.child('amount'); return paymentRef.child('balanceAmount').transaction(current => { return current - paymentDetailAmountSnapshot.val(); // Balance can be negative }); }); 

(Use a transaction to manage concurrent changes)

Transaction Documentation.

Note

Please use Number for the given String .

UPDATE

Add this function to manage the update:

 exports.recalculateBalance = functions.database.ref('payments/{pushId}/paymentDetails/{detailId}').onUpdate(event => { var paymentRef = event.data.adminRef.parent.parent; var paymentDetailSnapshot = event.data; var previousPaymentDetailSnapshot = event.data.previous; var paymentDetailAmountSnapshot = paymentDetailSnapshot.child('amount'); var previousPaymentDetailAmountSnapshot = previousPaymentDetailSnapshot.child('amount'); return paymentRef.child('balanceAmount').transaction(current => { return current + previousPaymentDetailAmountSnapshot.val() - paymentDetailAmountSnapshot.val(); // Balance can be negative }); }); 
+3
source

Source: https://habr.com/ru/post/1270422/


All Articles