firebase/snippets-node

I believe that this cloud function is not idempotent

schevtso opened this issue · 3 comments

exports.aggregateRatings = functions.firestore
.document('restaurants/{restId}/ratings/{ratingId}')
.onWrite((change, context) => {
// Get value of the newly added rating
var ratingVal = change.after.data().rating;
// Get a reference to the restaurant
var restRef = db.collection('restaurants').doc(context.params.restId);
// Update aggregations in a transaction
return db.runTransaction(transaction => {
return transaction.get(restRef).then(restDoc => {
// Compute new number of ratings
var newNumRatings = restDoc.data().numRatings + 1;
// Compute new average rating
var oldRatingTotal = restDoc.data().avgRating * restDoc.data().numRatings;
var newAvgRating = (oldRatingTotal + ratingVal) / newNumRatings;
// Update restaurant info
return transaction.update(restRef, {
avgRating: newAvgRating,
numRatings: newNumRatings
});
});
});
});

If it's retried, I think it's possible to get a wrong value for newNumRatings.

exports.aggregateRatings = functions.firestore
.document('restaurants/{restId}/ratings/{ratingId}')
.onWrite((change, context) => {
// Get value of the newly added rating
var ratingVal = change.after.data().rating;

   // Get a reference to the restaurant 
   var restRef = db.collection('restaurants').doc(context.params.restId); 

   // Update aggregations in a transaction 
   return db.runTransaction(transaction => { 
     return transaction.get(restRef).then(restDoc => { 
       // Compute new number of ratings 
       var newNumRatings = restDoc.data().numRatings + 1; 

       // Compute new average rating 
       var oldRatingTotal = restDoc.data().avgRating * restDoc.data().numRatings; 
       var newAvgRating = (oldRatingTotal + ratingVal) / newNumRatings; 

       // Update restaurant info 
       return transaction.update(restRef, { 
         avgRating: newAvgRating, 
         numRatings: newNumRatings 
       }); 
     }); 
   }); 
 }); 

exports.aggregateRatings = functions.firestore
.document('restaurants/{restId}/ratings/{ratingId}')
.onWrite((change, context) => {
// Get value of the newly added rating
var ratingVal = change.after.data().rating;

   // Get a reference to the restaurant 
   var restRef = db.collection('restaurants').doc(context.params.restId); 

   // Update aggregations in a transaction 
   return db.runTransaction(transaction => { 
     return transaction.get(restRef).then(restDoc => { 
       // Compute new number of ratings 
       var newNumRatings = restDoc.data().numRatings + 1; 

       // Compute new average rating 
       var oldRatingTotal = restDoc.data().avgRating * restDoc.data().numRatings; 
       var newAvgRating = (oldRatingTotal + ratingVal) / newNumRatings; 

       // Update restaurant info 
       return transaction.update(restRef, { 
         avgRating: newAvgRating, 
         numRatings: newNumRatings 
       }); 
     }); 
   }); 
 }); 

exports.aggregateRatings = functions.firestore
.document('restaurants/{restId}/ratings/{ratingId}')
.onWrite((change, context) => {
// Get value of the newly added rating
var ratingVal = change.after.data().rating;

   // Get a reference to the restaurant 
   var restRef = db.collection('restaurants').doc(context.params.restId); 

   // Update aggregations in a transaction 
   return db.runTransaction(transaction => { 
     return transaction.get(restRef).then(restDoc => { 
       // Compute new number of ratings 
       var newNumRatings = restDoc.data().numRatings + 1; 

       // Compute new average rating 
       var oldRatingTotal = restDoc.data().avgRating * restDoc.data().numRatings; 
       var newAvgRating = (oldRatingTotal + ratingVal) / newNumRatings; 

       // Update restaurant info 
       return transaction.update(restRef, { 
         avgRating: newAvgRating, 
         numRatings: newNumRatings 
       }); 
     }); 
   }); 
 });